From: Erich H. <er...@gm...> - 2005-04-01 09:29:12
|
Hey everyone, I'm in process of cranking out a crappy gaim plugin, but I am hoping to start working on SDLmm really soon. I know you are eager to see any work at all, since it's been 4 years since the last commit :P This post is mainly to put things on the table for discussion. Now David has said that he has specifically left exceptions out of the library... I understand that a project goal is to stay as close to SDL as possible, which means, of course, using return values for error checking. As much as I think this goal makes it easier on the programmer used to writing in SDL, I think that this attitude inherently means that some of the advantages of C++ are going to be lost (exception handling would be one, however small). I'm of the opinion that, with some degree of restraint, perhaps this goal should be stretched a bit to allow for further development / improvement and not just a stagnant project. David had already outlined his intention of adding "additional features" to SDLmm, such as the sprite class, but I wonder if this attitude can't be applied to the current source. Anyway, here's my case for exception handling: 1) Exceptions offer a consistent way of handling errors. We know that if an error occurs within the library, an exception will be thrown. No need to check error values, check global error variables, pass references or pointers to objects containing this type of information, etc... 2) Exceptions reduce the amount of code the user of the library has to write. Instead of having something like: if (SDL_CreateSurface(...) == -1) { /* error handling code */ } and then having to rewrite the same construct again each time we call a function, we need only put the body of main inside a try block, and we can write code without having to _worry_ about error handling. Motto: "less code? yayyy!" 3) Exceptions can hold additional information about the error, and not just an error code or something retrieved from a global variable. I know this is an advantage, somehow... :) There's a good discussion about exceptions on this page, if you're interested: http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=77463 Exceptions aside, before I actually DO anything, I want to read through the code thoroughly, and alongside reading, fixing it up a bit ... is there any coding convention being used for the project right now? Anyway, I'd like very much to hear peoples' feedback about exception handling. Any additional concerns / requests / comments about the library, or what could be done better would make my job a lot easier. Thanks all, Erich Herz |
From: Martin B. <bi...@as...> - 2005-04-01 16:27:44
|
Hi, it's nice to see some action at the SDLmm project again. We are using SDLmm for Advanced Strategic Command (www.asc-hq.org). The current version does not use it very much, but ASC2, which is currently under development, uses it to a much greater extent. Since we are using Paragui for dialogs in ASC2, I'll keep an eye that both libraries get along each other :) To make packaging and building of ASC easier, we included SDLmm in the ASC source package, so I could fix several problems with SDLmm without the need for an official SDLmm release. I'm attaching a patch with the fixes. The patch does not include changes that were necessary for building SDLmm with Borland C++ Builder. The RCSID macros caused conflicts, so I removed them all. IMHO, they have nothing lost in the global namespace. I suggest, if they are need at all, to at least put them into the SDLmm namespace. I also agree that error handling using exceptions is better than the current use of return codes. Martin |
From: David H. <da...@he...> - 2005-04-14 22:35:19
|
"Martin Bickel" <bi...@as...> writes: > The patch does not include changes that were necessary for building > SDLmm with Borland C++ Builder. The RCSID macros caused conflicts, so I > removed them all. IMHO, they have nothing lost in the global namespace. > I suggest, if they are need at all, to at least put them into the SDLmm > namespace. The purpose of RCSID macros is to allow the command "ident" to list the versions of the files in the library. Naturally with Borland C++, this is of no consequence. Example output: : 0 neotron@stellar ident ~/src/SDLmm/src/.libs/libSDLmm.so /home/neotron/src/SDLmm/src/.libs/libSDLmm.so: $Id: sdlmm_global.cpp,v 1.17 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_basesurface.cpp,v 1.18 2001/08/27 22:14:53 neotron Exp $ $Id: sdlmm_surface.cpp,v 1.18 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_display.cpp,v 1.14 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_pixelformat.cpp,v 1.5 2001/07/09 01:14:13 rad_ad Exp $ $Id: sdlmm_srect.cpp,v 1.9 2001/08/30 23:58:45 rad_ad Exp $ $Id: sdlmm_event.cpp,v 1.9 2001/08/27 02:11:14 rad_ad Exp $ $Id: sdlmm_audio.cpp,v 1.5 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_timer.cpp,v 1.7 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_joystick.cpp,v 1.5 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_cd.cpp,v 1.5 2001/06/25 23:24:52 rad_ad Exp $ $Id: sdlmm_videoinfo.cpp,v 1.4 2001/06/25 23:24:52 rad_ad Exp $ -- [ Below is a random fortune, which is unrelated to the above message. ] You will be the victim of a bizarre joke. |
From: David H. <da...@he...> - 2005-04-13 18:12:05
|
Erich Herz <er...@gm...> writes: > Hey everyone, > > I'm in process of cranking out a crappy gaim plugin, but I am hoping > to start working on SDLmm really soon. I know you are eager to see > any work at all, since it's been 4 years since the last commit :P > This post is mainly to put things on the table for discussion. > > Now David has said that he has specifically left exceptions out of the > library... I understand that a project goal is to stay as close to SDL > as possible, which means, of course, using return values for error > checking. As much as I think this goal makes it easier on the > programmer used to writing in SDL, I think that this attitude > inherently means that some of the advantages of C++ are going to be > lost (exception handling would be one, however small). I'm of the > opinion that, with some degree of restraint, perhaps this goal should > be stretched a bit to allow for further development / improvement and > not just a stagnant project. David had already outlined his intention > of adding "additional features" to SDLmm, such as the sprite class, > but I wonder if this attitude can't be applied to the current source. > > Anyway, here's my case for exception handling: > > 1) Exceptions offer a consistent way of handling errors. We know that > if an error occurs within the library, an exception will be thrown. > No need to check error values, check global error variables, pass > references or pointers to objects containing this type of information, > etc... This is true. > > 2) Exceptions reduce the amount of code the user of the library has to > write. Instead of having something like: > if (SDL_CreateSurface(...) == -1) { > /* error handling code */ > } > and then having to rewrite the same construct again each time we call > a function, we need only put the body of main inside a try block, and > we can write code without having to _worry_ about error handling. > > Motto: "less code? yayyy!" Also true. > 3) Exceptions can hold additional information about the error, and not > just an error code or something retrieved from a global variable. I > know this is an advantage, somehow... :) Yes, this is true as well. I will now add the negative effects of exceptions. 1) It complicates memory handling. I.e if you have code such as this: void myfunc() { Type *data = new Type(); Type->do_something(); delete data; } I do_something throws an error which is recovered properly by the method calling myfunc, we now have leaked a reference to Type. Often this can be mostly fixed by using some sort of automatic or reference counted pointer object, but it's still a potental issue. If automatic pointers aren't used, you would get code like (pseudocode example): void myfunc() { Type *data = new Type(); try { Type->do_something();} catch ExpectedError err { delete data; throw err; } delete data; } which really isn't an much improvement over: bool myfunc() { Type *data = new Type(); if(Type->do_something() != OK) { delete data; return false; } delete data; return true; } 2) Even if you always correctly catch errors (you expect) when you need to delete objects or handle the error, an unexpected exception could still result in leaks since you for whatever reason didn't handle it (sloppy programming or lack of knowledge of possible exceptions). 3) Exceptions are best used for exceptional errors. I.e errors that you cannot recover from. Using exceptions is slower than using normal error handling and does complicate coding in the case it's simply a warning or recoverable error. I'm not saying no to exceptions entirely but I'd really want to keep the "original" calling conventions there, perhaps with a define. Also SDL already has an error reporting mechanism. Sure it's a global error string, but it's there. I could definitely see an error object used which at its creation queries the error string and is then thrown. However from Java programming, where exceptions are used exclusively for errors, I can tell by experience that exceptions doesn't make programming easier (well C++ exceptions are somewhat different but similar never the less). > There's a good discussion about exceptions on this page, if you're interested: > http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=77463 > > Exceptions aside, before I actually DO anything, I want to read > through the code thoroughly, and alongside reading, fixing it up a bit > ... is there any coding convention being used for the project right > now? Err. Yes. Mine. :) Seriously, I typically write code like this: void foo(int x, string y) { char *bar; int i; if(bar == NULL) { ... } else if(foo) { ... } switch(i) { case 10: hello; case 1: gazonk } } with 2 character indentation, tab being set to the "standard" 8 characters. Emacs uses tabs/spaces automatically for indentation although I'm not against changing it to be purely spaces. Just don't code with an app that uses 2 or 4 or whatever char / tab. I also don't like code such as: if(X) { } else if(Y) { } else if(x) { } since it is rather unclear and space wasting compared to if(X) { } else if(Y) { } else if(x) { } I sometimes uses void foo() { } for functions. > Anyway, I'd like very much to hear peoples' feedback about exception > handling. Any additional concerns / requests / comments about the > library, or what could be done better would make my job a lot easier. Making it use either would be great: bool Display:Init(..) { int success = SDL_Init(..) == 0; #ifdef USE_EXCEPTIONS if(!success) { throw new SDLmm::Exception(ret); } #endif return success; } That would be backwards and SDL compatible with optional C++ exception error handling. I should say though that I haven't entirely stuck to SDL standard return codes. I typically translate the response to a boolean (true == success, false == error) where possible (i.e where SDL only has one error response). SDL typically uses -1 for ERROR, and 0 for OK. I like 'true' to be OK not ERROR. :) -- [ Below is a random fortune, which is unrelated to the above message. ] You'll wish that you had done some of the hard things when they were easier to do. |
From: Martin B. <bi...@as...> - 2005-04-13 19:37:07
|
On Wed, 13 Apr 2005 11:11:58 -0700, David Hedbor wrote: >I will now add the negative effects of exceptions. > >1) It complicates memory handling. I.e if you have code such as this: > >void myfunc() { > Type *data = new Type(); > Type->do_something(); > delete data; >} Then you have bad application code which you should fix, and not blame SDLmm for it :-> Since exceptions are the standard C++ mechanism for reporting errors and even the standard library uses them, you should write exception safe code anyway, regardless if SDLmm uses it or not. >I do_something throws an error which is recovered properly by the >method calling myfunc, we now have leaked a reference to Type. Often >this can be mostly fixed by using some sort of automatic or reference >counted pointer object, but it's still a potental issue. But the goal of SDLmm is to provide a C++ abstraction of the SDL functions. We shouldn't design the library around potential programs that for whatever reason don't use the C++ mechanisms for automatic memory management. If someone really wants to go the messy C way, he can call SDL directly. > >2) Even if you always correctly catch errors (you expect) when you > need to delete objects or handle the error, an unexpected exception > could still result in leaks since you for whatever reason didn't > handle it (sloppy programming or lack of knowledge of possible > exceptions). Ok, but an unexpected error return is far worse! An unexpected exception passes through several layours of the application until it is handled and the application can safely recover or cleanly exit. An unexpected error return goes totally unnoticed and the application either gets stuck or crashes without you having any chance to recover or even get an idea what the hell happened. >3) Exceptions are best used for exceptional errors. I.e errors that > you cannot recover from. Using exceptions is slower than using > normal error handling and does complicate coding in the case it's > simply a warning or recoverable error. I totally agree there. Exceptions are a mechanism to report and handle bad errors. They are not intended to replace return results. So we should perhaps go into detail and ask: which occasion are in SDLmm where an exception might be thrown? In my opinion, all File I/O errors should be handled through exceptions. Failed memory allocations as well (the new operator already does this, but SDL uses malloc...). Regards, Martin |
From: David H. <da...@he...> - 2005-04-13 20:15:09
|
"Martin Bickel" <bi...@as...> writes: > On Wed, 13 Apr 2005 11:11:58 -0700, David Hedbor wrote: > >>I will now add the negative effects of exceptions. >> >>1) It complicates memory handling. I.e if you have code such as this: >> >>void myfunc() { >> Type *data = new Type(); >> Type->do_something(); >> delete data; >>} > > Then you have bad application code which you should fix, and not blame > SDLmm for it :-> > Since exceptions are the standard C++ mechanism for reporting errors > and even the standard library uses them, you should write exception > safe code anyway, regardless if SDLmm uses it or not. Exceptions are optional (-fno-exceptions). And yes, the above is the error of the code but it does show why exceptions aren't all perfect for error handling. Error handling that makes it easier to get memory leaks could be bad if used too much. >>I do_something throws an error which is recovered properly by the >>method calling myfunc, we now have leaked a reference to Type. Often >>this can be mostly fixed by using some sort of automatic or reference >>counted pointer object, but it's still a potental issue. > > But the goal of SDLmm is to provide a C++ abstraction of the SDL > functions. We shouldn't design the library around potential programs > that for whatever reason don't use the C++ mechanisms for automatic > memory management. If someone really wants to go the messy C way, he > can call SDL directly. Automatic memory handling that's useful is something you need to implement in the application layer. My main point is that it's really really easy to make exceptions optional, enabled by default or not. I would go as far as suggesting a run-time flag to disable the use of exceptions. That way an app built on return codes will work with a library that has exception handling turned on. It will be mostly a free operation with little addtional code. No need to break backwards compatibility when it's so easy to maintain it. >> >>2) Even if you always correctly catch errors (you expect) when you >> need to delete objects or handle the error, an unexpected exception >> could still result in leaks since you for whatever reason didn't >> handle it (sloppy programming or lack of knowledge of possible >> exceptions). > > Ok, but an unexpected error return is far worse! > An unexpected exception passes through several layours of the > application until it is handled and the application can safely recover > or cleanly exit. > An unexpected error return goes totally unnoticed and the application > either gets stuck or crashes without you having any chance to recover > or even get an idea what the hell happened. That pretty much depends on the case. It's easy to "hide" the fact that something might thrown an exception (java is much better here since you have to declare that a function can throw an exception where in C++ this isn't the case). With return codes, you either get one or you don't and you can see on the function whether or not it returns something. Sure not handling the return code can have equally bad results. >>3) Exceptions are best used for exceptional errors. I.e errors that >> you cannot recover from. Using exceptions is slower than using >> normal error handling and does complicate coding in the case it's >> simply a warning or recoverable error. > > I totally agree there. Exceptions are a mechanism to report and handle > bad errors. They are not intended to replace return results. I would go as far as saying non-recoverable errors primarily. > So we should perhaps go into detail and ask: which occasion are in > SDLmm where an exception might be thrown? > > In my opinion, all File I/O errors should be handled through > exceptions. Failed memory allocations as well (the new operator already > does this, but SDL uses malloc...). As far as I know, you can't easily determine that an error in SDL occured due to failed memory allocation. You get "-1" return code and a textual representation of the error, not an "errno" type error code. How do you know if it's a memory related error? :) -- [ Below is a random fortune, which is unrelated to the above message. ] All the troubles you have will pass away very quickly. |