Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Four Star Mon
Index -> Programming, C++ -> C++ Submissions
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
Dratino




PostPosted: Wed Apr 06, 2011 5:35 pm   Post subject: Four Star Mon

Four Star Mon is a project to create an engine in C++ that can emulate the mechanics of the Pok?mon video games.

We're currently trying to recruit some members to help program, and what better place to do it than here?

Here's our website: http://fourstarmon.com/

In order to download the project, you'll need SVN. The instructions are here: http://fourstarmon.com/forum/showthread.php?tid=3

I can't post a demo or any files here at the moment because it only runs in Linux. Also, it's very very early on into development, so be prepared for a lot of things to not work.
Sponsor
Sponsor
Sponsor
sponsor
DemonWasp




PostPosted: Wed Apr 06, 2011 6:09 pm   Post subject: RE:Four Star Mon

I tried this out and managed to get a segmentation fault. Ubuntu 10.10.

Set up:
code:

(download using svn as directed by the link)
sudo apt-get install scons libsdl1.2debian libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev
./buildandrun.sh


Output:
code:

Done building ACTION.
Loading file: items.icl

Initializing game...
./buildandrun.sh: line 3: 21697 Segmentation fault      ./fourstarmon
Dratino




PostPosted: Wed Apr 06, 2011 6:57 pm   Post subject: Re: Four Star Mon

Hmm. Probably means that one or more of the files are missing. (I'm currently developing this on Ubuntu 10.10 as well.) Can you run GDB and get the backtrace? Would be very much appreciated.

Did you check it out from the SVN or download the package? Because I know the SVN is missing the sprites.
DemonWasp




PostPosted: Wed Apr 06, 2011 8:14 pm   Post subject: RE:Four Star Mon

I checked it out from SVN, because that's what it says in your link. If missing sprites cause a segmentation fault, you should probably fix that (error messages are much better than segfaults).

I don't do much C/C++ dev, so my gdb skills are pretty limited. When I told gdb to run your program, I got:
code:

Starting program: /home/demonwasp/code/fsm
[Thread debugging using libthread_db enabled]
Done building ACTION.
Loading file: items.icl

Initializing game...

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff6988c14 in ?? () from /lib/libc.so.6


It looks like you're making a bad call into the standard libraries to me (but what would I know, I don't use gdb or C++ ever if I can get away with it).

It's worth noting that this is on an x64 machine running 64-bit gcc/g++. Does the code expect a 32-bit machine?

Alternately, do you have more detailed gdb instructions / a page to follow to provide more information?
Dratino




PostPosted: Wed Apr 06, 2011 8:30 pm   Post subject: RE:Four Star Mon

No, I can't (sorry about that, one of the things we need is an error message system Sad), that seems correct to me. It seems to be because the sprites are missing, because the program (from what little of the output there is) seems to have compiled perfectly.

*edit* OK, the files are up.
DemonWasp




PostPosted: Wed Apr 06, 2011 9:18 pm   Post subject: RE:Four Star Mon

I looked up a GDB tutorial and typing "backtrace" is apparently a form of magic. I've managed to find two separate issues now, though.

First, as you suspected, lacking the sprites to load will give a segfault deep within src/GraphicsManager:493, as ssurf's value is never checked against NULL before dereferencing it.

Second, if you (perhaps foolishly) try to run the game in an environment that can't initialize a graphics context (such as an SSH connection that doesn't have X-forwarding on), you get a segfault because glGetString(GL_EXTENSIONS) returns NULL (soil/SOIL.c:1880) which is then passed to strstr.

You should really start testing for failures, failing as soon as you can detect a problem, and outputting error messages. Do this as soon as possible; it'll make it orders of magnitude easier to find problems in the future. If you're open to more advice, the next one is to write unit tests. Write them for everything you can. Fix things until they pass before coding new features (and update tests to cover new features). Never commit anything that doesn't pass 100% of your unit tests. You might think there aren't any bugs in your program, but I guarantee that there's probably around 1 bug per 100 lines, if not more. This is true of everyone -- I constantly find stupid mistakes in my own code because I tested it. This will save you time and stress later.
Dratino




PostPosted: Wed Apr 06, 2011 9:27 pm   Post subject: Re: RE:Four Star Mon

DemonWasp @ Wed Apr 06, 2011 9:18 pm wrote:
I looked up a GDB tutorial and typing "backtrace" is apparently a form of magic. I've managed to find two separate issues now, though.


A form of magic...? Not sure what you mean there.

Quote:
First, as you suspected, lacking the sprites to load will give a segfault deep within src/GraphicsManager:493, as ssurf's value is never checked against NULL before dereferencing it.

Second, if you (perhaps foolishly) try to run the game in an environment that can't initialize a graphics context (such as an SSH connection that doesn't have X-forwarding on), you get a segfault because glGetString(GL_EXTENSIONS) returns NULL (soil/SOIL.c:1880) which is then passed to strstr.


Well, I've never run the game in an environment without a graphics context, so... :/

Quote:
You should really start testing for failures, failing as soon as you can detect a problem, and outputting error messages. Do this as soon as possible; it'll make it orders of magnitude easier to find problems in the future. If you're open to more advice, the next one is to write unit tests. Write them for everything you can. Fix things until they pass before coding new features (and update tests to cover new features). Never commit anything that doesn't pass 100% of your unit tests. You might think there aren't any bugs in your program, but I guarantee that there's probably around 1 bug per 100 lines, if not more. This is true of everyone -- I constantly find stupid mistakes in my own code because I tested it. This will save you time and stress later.


I'm pretty new to the world of software engineering, so excuse me if I don't know how unit testing works.

And yes, because I've been changing the entire software layout around for the past few weeks, there are probably even more bugs than the 1 per 100 lines you're talking about.
Where would error messages go, by the way? Just into a log like I've been doing for some of them? Or should I use try/catch blocks that terminate the program as soon as it receives an error?

Because I've been planning on putting in error handling for quite some time, but have no idea how to start approaching it. Will it necessarily expand the code to twice its size? Because if that is the case, then I have some methods in which I could potentially do something, but then even implementing the error handling system would take lots of debugging by itself.

Would you like to join the development team, DemonWasp (or, if you're busy with other commitments, drop by for a tip on the website every now and then)? I know you don't do much C or C++, but your knowledge of software engineering (and perhaps your connections) could be invaluable. (Google is, too, but given the educational nature of this project for most of the people involved, it would be good to have a reliable source of advice.)
DemonWasp




PostPosted: Wed Apr 06, 2011 10:32 pm   Post subject: RE:Four Star Mon

By "magic" I meant that instead of spending hours hunting down the problem(s), gdb's "backtrace" provides a full stack trace of the most recent error (segfault). Incredibly useful.


It's understandable that you might not have run the game in XYZ environment. After all, everyone does things slightly differently. The correct thing to do here isn't to test in all possible environments (completely impossible), but to check your return variables. Somewhere you have an initialization call to OpenGL that can return an error value, but that return value is ignored. This is poor practice: always check whether the operation you just ran succeeded.


As a start to error handling, you need to decide whether you'll use C's older style, or the C++ exception-handling mechanism. The C style is more straightforward, but looks a lot messier in code; the C++ style is far more complex, but leads to nicer code.

The C Way
In C, most methods that can fail or have a status other than "returned" will return an int to describe the status of this operation. You see this pattern a lot in string-manipulation and I/O methods (most of which return a length of data acted upon, such as bytes loaded from a file or characters copied). Some other functions will return 0 on success or another number on failure (main is expected to do this); the number describes the type of error.

This way leads to code that looks like this:
code:

int first_op_error = first_operation ( args );
if ( first_op_error == NO_ERROR ) {
    int second_op_error = second_operation ( other_args );
    if ( second_op_error == NO_ERROR ) {
        // to be continued...
    } else {
        // operation 2 failed...
    }
} else if ( first_op_error == ERROR_TYPE_1 ) {
    // handle error type 1 from first operation...
} else {
    // unknown error type from first operation
}


This will prevent second_operation from being called if first_operation fails. However, it also leads to a lot of code to handle errors, which may be a contributing factor to a lot of early games having cryptic and unhelpful error messages (or, to them simply crashing and burning whenever a problem happens).


The C++ Way
In C++, methods that can fail may "throw" exceptions that can later be caught. An exception propagates up the stack until it is caught by a process known as the "exception handling mechanism". The code you end up writing is a lot neater (see below), and you can provide a lot more information about the error easily (by having member variables inside your exception types). You will, of course, have to use some C-style error-handling, particularly when dealing with methods that also exist in C or when checking against NULL.

C++ also helpfully lets you do silly things like throwing integers. You can throw whatever you like, really -- pointers, characters, bytes, enumerations, ...

code:

try {
    if ( NULL == first || NULL == second ) {
        throw new NullPointerException();
    }
    first->operation ( args );
    second->operation ( args );
} catch ( FirstOpError1 * e ) {
    // handle error type 1 from first operation...
} catch ( SecondOpError1 * e ) {
    // operation 2 failed...
} catch ( BaseException * e ) {
    // unknown error type from first operation
} finally {
    // deallocate memory here...
}


Nicer, right? Well, there are more than a few "gotchas" with this mechanism. First, you need to move all your delete() / free() calls into a finally {} block, or else they will NOT be called when the stack is unwound -- this will leak memory. Second, there are approximately a billion different ways you can screw up throwing and catching objects; for more detail, see the C++ FAQ: http://www.parashift.com/c++-faq-lite/exceptions.html .


In fact, let's make that obvious to everyone who looks at this thread: C++ FAQ HERE


Unit Testing
Unit tests are designed to let you make sure that the small, indivisible chunks of your program, "units", work as you intended. They are a way to tell the computer what your requirements for a given code file are, so that it can check them for you. Once you have a good suite of unit tests, you can change code without worrying too much about whether you just broke something elsewhere -- just run the unit tests, they'll tell you what broke and where. For C++ unit-testing, see http://cpptest.sourceforge.net/ , or look around. There are plenty of options, including scripting your tests from another language (I hear Python is a common choice).

Do whatever you think will help you write the most unit tests.
Sponsor
Sponsor
Sponsor
sponsor
Dratino




PostPosted: Thu Apr 07, 2011 12:31 pm   Post subject: RE:Four Star Mon

Thanks for all that.

Um... I put the sprite files up. They're on the instruction page again.

Would you like to try running it again?

(Also, would it be acceptable to use a customized exception class that isn't std::exception? I know that it will work, but as to whether it's good practice, I can't really say much.)
DemonWasp




PostPosted: Thu Apr 07, 2011 1:52 pm   Post subject: RE:Four Star Mon

I'll try it again when I get home -- assuming I remember. That probably won't be for a while as I'm going to a political rally after work. I'll let you know the results.

You can use other types of exceptions, but in general they should extend std::exception (just because that's supposed to be the root type for all exceptions). Is there a particular reason that you didn't want to extend std::exception?
Dratino




PostPosted: Thu Apr 07, 2011 3:23 pm   Post subject: Re: RE:Four Star Mon

DemonWasp @ Thu Apr 07, 2011 1:52 pm wrote:
You can use other types of exceptions, but in general they should extend std::exception (just because that's supposed to be the root type for all exceptions). Is there a particular reason that you didn't want to extend std::exception?


Oh, it's just because I thought I could get away with using my own exception class because I didn't want to leave any part of the class unused if I was going to extend it, and the "char* what" part of it would definitely stay unused because I'd have my own handling techniques for messages.

Basically, I'd create my own "error message" class and use that in place of exceptions.
DemonWasp




PostPosted: Thu Apr 07, 2011 11:03 pm   Post subject: RE:Four Star Mon

Even if you left that field as NULL, you'd only be saving sizeof ( char* ) bytes per exception (usually 4 or 8). Given the other costs in an exception, I don't think you're likely to notice any kind of problem stemming from that. If nothing else, use that pointer to point to a string contained in your own error mechanism. You should extend std::exception ; ideally, you would have the "what" field point to a descriptive string.

Also, I might just be dumb, but I don't see the sprite files on either of the links you've posted. Where should I be looking?
Dratino




PostPosted: Fri Apr 08, 2011 7:40 am   Post subject: Re: RE:Four Star Mon

DemonWasp @ Thu Apr 07, 2011 11:03 pm wrote:
Even if you left that field as NULL, you'd only be saving sizeof ( char* ) bytes per exception (usually 4 or 8). Given the other costs in an exception, I don't think you're likely to notice any kind of problem stemming from that. If nothing else, use that pointer to point to a string contained in your own error mechanism. You should extend std::exception ; ideally, you would have the "what" field point to a descriptive string.


I know about the descriptive string thing. It's just that I prefer working with std::string instead of char*. If I could make the pointer point to a std::string instead of a char*, I'd use the std::exception thing.

Quote:
Also, I might just be dumb, but I don't see the sprite files on either of the links you've posted. Where should I be looking?


On the forum post, second line.

"Note: These files themselves, for the current moment, will not be enough to run the program. You need the sprite folder. After checking out the SVN, download the sprites.zip file, from [url="http://www.mediafire.com/?9stfguh8sz3gxfq"]here[/url], and extract the sprites folder to the root directory of the project."
Display posts from previous:   
   Index -> Programming, C++ -> C++ Submissions
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 13 Posts ]
Jump to:   


Style:  
Search: