PDA

View Full Version : About using C++ exceptions


derlogiker
06-08-2007, 12:19 PM
Hello,

I'm fairly new to game programming. I was wondering if, in your experience, using C++ exceptions in games does introduce noticeable overhead. I had similar worries with the STL, but after some research, it seems there is no important overhead (if any). But what about exceptions? Would it be fine if I wrap the main loop of the game with a try...catch?

Any advice is appreciated,

Thanks!

PeterM
06-08-2007, 01:15 PM
There's pretty much no overhead.

Essentially, a "try" costs you very little (if anything). Throwing and catching costs, (identification of stack frames to unroll, unrolling of stack frames and destruction of objects), but that's hopefully in an "exceptional" error condition, which doesn't happen often.

Basically, don't worry about it, but don't throw all the time!

There could even be a performance boost, because you rely on the exception handling system to pass errors to code which can deal with them instead of having numerous (possibly bugged) if-else/switch error code handling blocks.

GBGames
06-08-2007, 01:27 PM
Hello,

I'm fairly new to game programming. I was wondering if, in your experience, using C++ exceptions in games does introduce noticeable overhead. I had similar worries with the STL, but after some research, it seems there is no important overhead (if any). But what about exceptions? Would it be fine if I wrap the main loop of the game with a try...catch?

Any advice is appreciated,

Thanks!

There is some debate about the merits of using exceptions, but even the people who are against sprinkling them throughout code seem happy enough with surrounding the main() function with a try catch.

As for performance, you had better be doing some cutting edge stuff if you are that concerned about the overhead of exceptions. You can always try it out in a prototype, and if it turns out that what you want to do might be adversely affected, take them out.

Applewood
06-09-2007, 04:01 PM
I can't say I've ever understood the point of them in games tbh.

They were probably invented because it was noticed that you couldn't return an error code from a constructor. I just don't do anything that can fail inside a constructor - they're not meant to load your level.

Anything else you can return check on. It's safer that way imo as I've seen exceptions overused and I've seen them badly used, but I've never seen "if (!value) return null;" ever go wrong or do anything odd.

To be perfectly honest, I don't stress about error returns too much as there's usually bugger all you can do about any of them. I handle error returns from routines that are *designed* to be failable and ignore ones that aren't.

tau
06-09-2007, 06:32 PM
Avoid using exceptions unless there is no other way to check for an error.

A person who says that exceptions do not have overhead does not have a lot of experience with them (no offense), or experience in profiling and optimizing code (VTune, etc).

Throwing and catching an exception is very expensive in terms of CPU cycles, because it jumps from your code into the system layer, searches for the appropriate exception class, then goes through many things until it hits the "catch" clause (check the stack view in your debugger right after the exception "throw" point).

Do a small experiment yourself - make you functions, one of them checks an error condition, and another throws an exception. Run those functions in a loop like 100,000,000 times, and dont forget to measure the total time of the execution. You'll see it for yourself.

If you can check for a null variable, or error code manually, do it.

James C. Smith
06-09-2007, 11:31 PM
I was wondering if, in your experience, using C++ exceptions in games does introduce noticeable overhead.

Do use exceptions for things that are the exception not the rule (things that happen rarely). It is very efficient to use try, often more efficient than checking for errors or result codes. But actually throwing an exception is very costly. You would never want something like an enemy AI that uses exceptions to handle the case of what to do when he tries to fire his gun but is out of ammo or the target is out of range. Cases like this, that could happen often, are not a good use of exception handing and would be more appropriate for result codes. But exceptions could be useful (and more efficient that checking tons of result codes) for something like handing error when parsing the file format of the assets that you load off disk.

The point is, exception handing makes the exceptional case get handled very slowly, but the normal case, where no exception is thrown, is usually as fast as doing no error checking at all (faster than doing result code checking)

James C. Smith
06-09-2007, 11:41 PM
Throwing and catching an exception is very expensive

That is why you want to use them for exceptional thing that almost never happen and not use them for things that you expect to happen 1% of the time or more.



Do a small experiment yourself - make you functions, one of them checks an error condition, and another throws an exception. Run those functions in a loop like 100,000,000 times, and dont forget to measure the total time of the execution. You'll see it for yourself.

Now try that same experiment but this time never throw an exception. Or only throw it one in 100,000,000 times. It is just extra work to be checking error conditions that you know do not happen in 99,999,999 tries.

Exception handling is like write the program so that it assume the exception will never happen and then if the exception does happen it rewrites the program on the fly to handle the exception. It is slow very to do this “re-writing”, but it can be worth it if it almost never happens and all those non-exceptional cases to be optimized to assume no failures and not have to check results.

Fabio
06-10-2007, 01:03 AM
There's both memory and CPU overhead even if the C++ exceptions are never thrown.

I only use SEH exception mechanism with my own handler, and I have my own per-thread signaling system for less critical error handling when I don't want to return an error as a return value from a function.

My advice is stay away from (i.e. DISABLE support in compiler switches) RTTI and EH!!!

Even RTTI, while being a good idea, places too much overhead. I preferred to implement these functionalities with my own low-level code where and only where necessary, because I know more things about my program than the compiler can know or pretend to infer.

I do also use templates a lot, but not the STL.

Face it, C++ is an evolution from C, which is a low level language. The worst defects of C++ programs come when people pretend it's a high level language..

PeterM
06-10-2007, 04:29 AM
There's both memory and CPU overhead even if the C++ exceptions are never thrown.
Even if true, how does it compare to the thorough manual error checking required to reach the same quality of robustness? Remember that at each "return" which the programmer adds during manual error checking, the compiler is going to generate some destruction code anyway.

In general, anti-exception sentiment seems to be based on comparing oranges to apples and "not written here" syndrome.

Not having any error handling at all is not an argument against using exceptions - the alternative is manual checking, which is error prone, adds a lot of ifs/switches, and obfuscates the code.

Gary Preston
06-10-2007, 06:48 AM
I was under the impression that exceptions introduced an overhead even when the code you call hasn't thrown anything, I read somewhere this was in the region of 10% extra code to allow unwinding the stack. You also have the runtime overhead of pushing extra data onto the stack to enable the unwinding.

I've heard there are exception handling methods that can be zero-cost unless an exception is thrown, but afaik Visual Studio/GCC etc do not implement this style of exception handling.

I'd be interested in hearing from anyone knows of any kind of benchmarks with exceptions compleatly disabled via compiler switch vs exceptions enabled but not used vs exceptions used. Especially if it was attempted with a variety of compilers.

Whether the overhead is something you can live with for the added benefit they bring, is probably going to be a game specific question only you can answer. For most typical indie games, it's probably not going to make much of a difference. You could always #define your own try, catch calls allowing you to remove exceptions from your code with a single change at a later date, that way you get all the benfits of exceptions during development and can avoid the overheads during shipping if they turn out to be a problem.

Just make sure you take onboard the advice of other posters and avoid using exceptions for anything other than "exceptional" cases. If you expcet an error to occur during normal operation, then you should be returning error codes rather than throwing exceptions.

Not having any error handling at all is not an argument against using exceptions - the alternative is manual checking, which is error prone, adds a lot of ifs/switches, and obfuscates the code.

Exceptions arn't an alternative to manual checking imho, they should be used in addition to standard error return codes. The return codes used to test for error conditions that you expect to see now and then during runtime, whilst exceptions are there to catch those errors that you don't ever expect to see, but _could_ feasibly occur. For example hardware failure.

I wonder if the lack of error checking in most peoples code stems from the very first time we're taught to program, for example most programming books "omit" error checking code for readability, this occurs from beginner books all the way to more advanced books dealing with specific techniques. It makes me wonder if people see code with error checking as messy solely for the reason they've become so used to seeing code without it.

KatieL
06-10-2007, 12:22 PM
We write pretty high performance code running on Linux. In C++. With trimmings. And by trimmings I mean, exceptions, catches, templates, STL, polymorphism, RTTI and all the jazz that everyone over the years keeps telling me makes C++ slow and unweildy.

By "high performance", I mean realtime on-demand video delivery to tens of thousands of users. That kind of thing.

We do find that we have performance problems, of course.

Even multiplexing disk IO down inordinately expensive multi-channel controllers, it's too slow. Seek times on 10k disks are flipping annoying. And we cannot ram enough data down the internetwork connections because they top out at a gigabit. The rack backplate connections will run at 10gigabit but put out EM radiation in ways that violates all sorts of US import regulations.

Things like that. We're in a world where the appallingly slow speed of light is a problem that bugs us daily. And yet, we've not yet come across a point where the not throwing exception track in code in GNU C++ makes a dent in performance not massively outweighed by the other loads in the system.

I can pretty much promise you, after a decade and half in this industry, that algorithmic optimisations[1] would be a better use of your time than worrying about C++ minutae. Write the code with exceptions[2]. Later on, if your profiler tells you that's where your problem is, fix it then[3][4].



[1] You'd be amazed how often I see people faffing about doing things like removing virtual dispatching from a system to try and speed up their O(N^2) solution to a problem because they've never read the textbooks which explain the O(log2 N) solution.

[2] Because it will be more maintainable. And if you're a new C++ developer, you will welcome the readability.

[3] Premature optimisation is the curse of this industry. Don't optimise code until you absolutely have to. And absolutely don't optimise it until you have WRITTEN IT.

[4] Get a profiler. Do not try to optimise by guessing. There be dragons.

Fabio
06-11-2007, 02:22 AM
Even if true, how does it compare to the thorough manual error checking required to reach the same quality of robustness? Remember that at each "return" which the programmer adds during manual error checking, the compiler is going to generate some destruction code anyway.
Let away that the destruction code can be a mere JMP, what I was meaning is a matter of design. You should not use exceptions (which are a great thing, although I disagree that the C++ EH model is efficient enough to be as good as most of the rest of the language) just to say if a function returned a certain condition. Some coders would throw an exception if e.g. a player is trying to fire a missile but has none left. That's plainly wrong IMO, in that case the result should be returned as a coded value. As far as I can see, exceptions are often abused and should be used only for.. exceptional cases you don't want to handle via return codes just because they represent a mulfunction. Having no missiles left and trying to fire one is not a malfunction, but a stupid condition, so to speak.
For a low level example, a square root function returns the square root of its argument, which should never be negative. If it is, then it's a design problem, or a bug, or a "violation of a contract", and thus an exception should be thrown. It makes no sense to check all the time if the argument of a sqrt() is negative, it's supposed to be a waste of CPU time and of source code. Another example, this time high level, is when you've to load the files of a level. They are supposed to be there, you should not check their presence explicitly just because the user may have deleted some files, but if a file is not found, an exception should be thrown. This exception will be generated by your LoadFile() function, thus at the lowest level, although it involves a high level part of your program (the level loading code). Per contra, having no error checking code when trying to load a file is as bad as it could be.
As I said I don't rely on C++ EH and RTTI because I think their overhead is unacceptable (whatever its absolute amount may seem, it's relatively abnorm, just disassemble some code with and without EH or RTTI), but I do rely a lot on exceptions in the way and limits described above, but with my own exception handler (SEH for hardware exceptions, and my own per-thread signaling system for software exceptions).
C++ EH are "overfeatured" IMO, for my exception model there's no need to unwind the stack: I work on big chunks, e.g. if you start a level, then a big block of memory will be allocated (NOT from the heap but from the stack (in my EXE and CreateThread startup code I set the thread stack to max size via the TIB after having allocated a very big chunk of memory via VirtualAlloc), I use the heap as little as possible because the stack has a "depth" nature which follows the execution of code, while the heap is more for system-level, global allocations, shared by all threads and with a lifetime possibly infinite), if the level function has to return, then I simply free that whole block at once (from which sub-blocks were allocated for objects by thousands other functions called directly or indirectly by that main function) by simply resetting the ESP CPU register to the right value (lightspeed memory freeing). Objects which perform more than a mere allocation of memory, will have in their constructors a special call that records in a per-thread list what functions have to be called in case the exception won't return, i.e. an "exceptional destructor" (my exception system can return in case it's able to fix the problem (e.g. a file requester and the user fixs the problem) and when it returns it's as if nothing happened). This is someway equivalent to unwinding the stack, but does it only where and when necessary, and is much more efficient. This because in my experience C++ destructors are most of the time used just to free memory, and for no other truly important task (or not indispensible task in case the object has to be terminated, that's what I mean, I use destructors for ending objects normally).
C++ EH is more automatic but has also more overhead and doesn't let you continue after an exception even when you could have fixed the problem and filtered the exception.
In any case, exceptions got that name not by coincidence, so they should not be used for "informative" purposes, but just to handle special cases which, in a well working system, are never supposed to happen (and that's why handling them in return codes would be overkill and a true waste of source code and CPU time).

PS: Sorry but English is not my native language and I'm also in a hurry, I've tried to re-read what I wrote and it's not really the greatest example of well written English technical post.

Paul-Jan
06-13-2007, 02:33 AM
[4] Get a profiler. Do not try to optimise by guessing. There be dragons.

Amen. And spend some serious time learning how to use it.

ZeHa
06-13-2007, 03:51 AM
You would never want something like an enemy AI that uses exceptions to handle the case of what to do when he tries to fire his gun but is out of ammo or the target is out of range

I agree to that, and that's of course why it's called an exception. Exceptions should really only be used when things happen that shouldn't happen, so their execution is very unlikely. It's like a safety net in a circus - just for the case. But never ever it should be used for normal program flow (like a, let's say, alternative to an "if" statement ;) )

EDIT: ...and so, it should be clear that their overhead is completely unimportant, because since they are only the safety net, they will only occur if something serious is happening. And then, there's no need to worry about performance issues.

Applewood
06-13-2007, 05:04 AM
"exception" doesn't derive from "exceptional" btw, it's an old hardware term.

Throwing an exception is what a CPU does in response to a divide by zero or stack fault, etc. In reality this might cause an interupt or Trap instruction to branch the code elswhere, usually without coming back. This type of error response is known as exception handling by the hardware guys.

This link below is the best example I could find in a 30 second google session about the origin of the phrase and how it's been used in low-level programming for decades....

http://www-scm.tees.ac.uk/users/u0000408/Excepts/Excepts.htm

I'm not just being pedantic. The entire nature of exception handling in C++ should be the same as the low-level description - for handling severe program fuckage only. If you can't actually handle it, as you usually can't in the middle of a game, then don't try to. Which leads me back to where I came in...

MedievalElks
06-15-2007, 09:37 AM
Do a small experiment yourself - make you functions, one of them checks an error condition, and another throws an exception. Run those functions in a loop like 100,000,000 times, and dont forget to measure the total time of the execution. You'll see it for yourself.
.

Catching an exception in main() happens once per execution of a game, not 100,000,000 times.

MedievalElks
06-15-2007, 09:41 AM
Face it, C++ is an evolution from C, which is a low level language. The worst defects of C++ programs come when people pretend it's a high level language..

Utter nonsense. C++ can be used to write both low and high level code.

Fabio
06-15-2007, 10:18 AM
Utter nonsense. C++ can be used to write both low and high level code.

Also assembly can, but it's utter nonsense to do that.

*You*'re better with C# or Java, trust me, if you think that C++'s efficiency is well represented by RTTI and its EH model.

tau
06-15-2007, 11:15 AM
Catching an exception in main() happens once per execution of a game, not 100,000,000 times.

We were discussing another case, and even so, the compiler adds some code to the finale binary, so weather you use exceptions or not, you end up wasting CPU cycles anyway

MedievalElks
06-15-2007, 09:21 PM
Also assembly can, but it's utter nonsense to do that.

*You*'re better with C# or Java, trust me, if you think that C++'s efficiency is well represented by RTTI and its EH model.

Who said that? And why would you use RTTI when you should be using polymorphism instead? Write in plain C if you're going to use C++ that way.

Fabio
06-16-2007, 12:59 AM
Who said that? And why would you use RTTI when you should be using polymorphism instead? Write in plain C if you're going to use C++ that way.
Your knowlegde of C++ appears to be so limited that to keep talking with you is only wasted time. Do your sterile polemics with someone else who has got free time to dedicate to you.

Greg Miller
06-17-2007, 07:42 PM
Even if true, how does it compare to the thorough manual error checking required to reach the same quality of robustness? Remember that at each "return" which the programmer adds during manual error checking, the compiler is going to generate some destruction code anyway.

In general, anti-exception sentiment seems to be based on comparing oranges to apples and "not written here" syndrome.

Not having any error handling at all is not an argument against using exceptions - the alternative is manual checking, which is error prone, adds a lot of ifs/switches, and obfuscates the code.

The classic C-style "return/if" method is rather expensive on modern processors (branches in general are pretty expensive, as an incorrect guess by the CPU tends to result in the pipeline being flushed).

How expensive exceptions are depends on the implementation method. The latest technique is to record the addresses of functions that have destructor calls to make separately from the actual code and look the functions up by their return addresses if an exception is thrown. That way, you don't execute any code at all for error-handling unless an error actually occurs. Error-handling is never going to get any more free than that.

Of course, not every compiler and ABI uses this method. Off the top of my head, I couldn't tell you which ones do.

MedievalElks
06-22-2007, 05:14 AM
Your knowlegde of C++ appears to be so limited that to keep talking with you is only wasted time. Do your sterile polemics with someone else who has got free time to dedicate to you.

I'm lacking in knowledge of C++ because I prefer polymophism to if-else blocks and RTTI? If you say so...

Fabio
06-22-2007, 10:29 PM
I'm lacking in knowledge of C++ because I prefer polymophism to if-else blocks and RTTI? If you say so...

No, it's because you think that if-elseif-elseif-elseif-elseif-else-blocks and RTTI are there as an alternative to Polymorphism, which is plain senseless to think.

MedievalElks
07-08-2007, 06:37 AM
No, it's because you think that if-elseif-elseif-elseif-elseif-else-blocks and RTTI are there as an alternative to Polymorphism, which is plain senseless to think.

Certainly not the only use of RTTI, but it's a common bad smell in C++ code. I've seen it in code for years. I'm not saying that I recommend the practice, in fact quite the opposite.

bvanevery
07-08-2007, 07:20 AM
To be perfectly honest, I don't stress about error returns too much as there's usually bugger all you can do about any of them. I handle error returns from routines that are *designed* to be failable and ignore ones that aren't.

Indeed. Most of these comments have been about performance. But, in my view, error checking rituals are a serious waste of time at various points in your development. Particularly at the prototyping stage. You may pretend you're going to throw and catch all these errors, or pass return values and implement graceful fallbacks for everything, but you won't. Probably your code will change 5 more times before your design stabilizes, and any mental masturbation you spent on error checking will prove thoroughly useless.

Since I don't know what the error handling policy should be in advance, I just "log and warn." That way, I've made a note in the code that an error is possible, and that an error is happening, but I don't try to do anything about it. I don't pass errors around in hierarchies until I know there's a good reason for it. That's just passing the buck.

GolfHacker
07-08-2007, 01:18 PM
I never use exceptions. They're a pain. First problem: most coders don't know how to use exceptions properly (i.e., they throw exceptions more often than they should). They're supposed to be exceptional. I've seen people throw exceptions from functions just so they can send back an error message or state information along with the return result. I've seen people throw them to terminate a loop. Those are bad designs. Second problem: if there's no catch to catch the exception, your program dies - this is far worse than just returning an error code and having the caller ignore it. Third problem: it can be confusing to follow the flow of logic or to debug because of the way you leap around the program when a exception is thrown - with a lot of debuggers, you can't even tell where the exception was thrown FROM. Visual Studio at least lets you break when an exception occurs, but not all debuggers provide this option.

Here's some additional information about performance with exceptions from the book, "More Effective C++" by Scott Meyers - a book EVERY C++ programmer should read and have on their shelf:

1. Exception handling has costs, even if you never use the keywords "try", "throw", or "catch". You pay for the space used by data structures to keep track of which objects are full constructed, you pay for the time needed to keep these data structures up to date. These costs are modest, but programs compiled without support for exceptions are typically faster and smaller than those that do have exception support built in.

2. You pay whenever you use a try block (i.e., whenever you decide you want to be able to catch exceptions). The cost varies from compiler to compiler, but in general your code size will increase 5-10% and your performance will decrease by about the same amount. This cost comes from just having the try block, and does not include catching anything.

3. Throwing an exception is the most costly, obviously. This typically shouldn't be a concern because exceptions should be rare (unless you're one of those bad coders who use exceptions when you're not supposed to). Compared to a normal function return, returning from a function by throwing an exception may be as much as three orders of magnitude slower, according to the benchmarks that Scott Meyers references. That's a big hit. But you only take the hit if you actually throw an exception, which should be never.

As GBGames said earlier, most casual and indie games probably don't need to be too concerned. It's only if you're doing some seriously intense real-time rendering that you need to worry. To minimize the performance overhead, compile without support for exceptions whenever possible, limit your use of try blocks to those locations where you really need them, and throw exceptions only under conditions that are truly exceptional.

Bad Sector
07-08-2007, 01:50 PM
Exceptions are a hack for C++'s (and most other OOP-enabled languages) inability to make a constructor return NULL :-P.

Ok, they're more than that, but i believe that it's very rare to really need them (which somehow justifies their name).

But i would love to have a C++ constructor return NULL :-). Why do

Foo bar = new Foo();
if (!bar.init("lala.dat"))
{
delete bar;
return 0;
}

when you can simply do

Foo bar = new Foo("lala.dat");
if (!bar) return 0;

I don't see any reason on why a constructor cannot do something fail-able. After all it constructs the object and it's construction can fail.

Backov
07-08-2007, 02:20 PM
Because having a constructor fail is an exceptional occurrence and shouldn't need to be checked.

Bad Sector
07-09-2007, 01:30 AM
Because having a constructor fail is an exceptional occurrence and shouldn't need to be checked.

Why is an exceptional occurence?

If i have an Image class that loads an image file from it's constructor it's plain normal to want to return NULL from the constructor if the image loading fails. Or when i allocate memory for an empty image, the allocation may fail. This is stuff that, for convenience, i would like to put in constructors. However C++ doesn't provide me with a clean mechanism to do that (i can do it using exception - pretty much the same how Java uses their exceptions - but i don't consider this mechanism "clear"... a "return NULL" would be more appropriate IMHO).

Of course, i could use creation functions, like newImage or createImage, etc which can return NULL (and that's what i'm doing usually) but this is doing more work for something that could be solved if the language had this little feature.

Fabio
07-09-2007, 01:53 AM
What about static objects? How would the language handle a failed constructor in that case?

As you see C++ is so full of features and possibilities that some apparently obvious things cannot be implemented because they would break something else.

C++ is far from being perfect, but it's still probably the most powerful and productive system language out there, and to a big extent not only "system".

Bad Sector
07-09-2007, 02:42 AM
What about static objects? How would the language handle a failed constructor in that case?

I thought about that. I didn't meant that "return NULL" should be the real method. It could be something else. Something that simply invalidates the object.

Or it could just not allow static objects when the return statement is used in constructors.

C++ is far from being perfect, but it's still probably the most powerful and productive system language out there, and to a big extent not only "system".

I disagree. C++ is just more popular because it is an extension and most compatible with C, which *is* a very good language. C++ is just a monster and some features are plain uglyness (dynamic_cast<bleh>(omg) anyone?). Unfortunately it's also the only "C extension" that can use C code almost as-is and provide object oriented features.

Anyway, this discussion has no point. C++ doesn't have this thing..

(of course i can always hack into g++'s source and add it myself, but that doesn't mean that it'll be added in the official g++)

GolfHacker
07-09-2007, 07:51 AM
Why is an exceptional occurence?

I think maybe you're doing too much work in your constructor. A constructor should be as compact as possible in order to reduce overhead and minimize errors. The constructor is called every time an object is created - this often occurs without your control, such as when the compiler creates temporaries. Only do what is minimally necessary during construction, and especially in a default constructor.

Another thing to consider: if you throw an exception from a constructor, the object's destructor is NOT run. This results in a memory leak.

One alternative is to use a smart pointer, like std::auto_ptr. The smart pointer will automatically delete the object when the smart pointer dies, even if there was a problem during instantiation.

Another alternative is to use your constructor to only initialize class members to default values (pointers to null, etc), then have a separate initialize method to perform the bulk of the real initialization. To save your callers the extra line of code, you can implement a factory pattern or perhaps a static creation method that does the work like this:

MyClass*
MyClass::instance()
{
MyClass* myobject = new MyClass();
myobject->initialize();
return myobject;
}

You can put any kind of error handling you want in here, your initialize method can return error codes, or whatever.

lennard
07-09-2007, 07:57 AM
Interesting discussion for a Monday morning. Off for a constitutional to think about my strategy of write quickly, tossing out the bits that aren't fun as I go along - I think mostly I need to get back into the habit of cleaning up (should that be refactoring?) my code as my projects progress. I would generally agree with Applewood that once something in the game fails then you are hooped as my games aren't written to be fault tolerant, they are meant to be bug free when they ship. That said, having some kind of function (I use Exit with a variable length list of parameters) to report back why the game got screwed can at least give you a starting point (and a log is better).

Anyhow, got a chuckle out of the "sterile polemics" line. Sounds like baffle 'em with bullshit or, I'm clearly so much smarter than you are that you shouldn't even try to argue with me. Lighten up dude.

Fabio
07-09-2007, 08:02 AM
I thought about that. I didn't meant that "return NULL" should be the real method. It could be something else. Something that simply invalidates the object.
But a lot of code can still be written to directly access the static object. Should the language be defined so that the code that refers to those objects gets automatically deleted? Only the statements or the whole functions?

Or it could just not allow static objects when the return statement is used in constructors. One of the most sucky things in a language is the lack of orthogonality. Learning thousands rules and millions crossed exceptions to those rules (Intel anyone?).

As you see there's no way you can do it in a coherent way with static objects (which HAVE their use, also for performance reason), not without introducing eventually a lot of virtualization and thus overhead.

Your solution may work but will only add confusion to an already very confused language.

I disagree. C++ is just more popular because it is an extension and most compatible with C, which *is* a very good language. Don't forget that C++ wasn't only meant to be an extension of C, but someway the "definitive" language. I don't think they* succeeded, anyway. ( *they because it's not only Bjarne, you know. Just like Linux is not only Linus.. )

C++ is just a monster and some features are plain uglyness (dynamic_cast<bleh>(omg) anyone?). I think the same.. but that doesn't mean that you've to take the whole C++ monster or nothing. C++ offers a lot of stuff, it's up to you to know what can be useful to your application and what can be overkill. Remember that some are there just to please the whole committee.

Unfortunately it's also the only "C extension" that can use C code almost as-is and provide object oriented features.

Anyway, this discussion has no point. C++ doesn't have this thing..

(of course i can always hack into g++'s source and add it myself, but that doesn't mean that it'll be added in the official g++) Perhaps you can, but not with static objects anyhow. ;)

Fabio
07-09-2007, 08:12 AM
Anyhow, got a chuckle out of the "sterile polemics" line. Sounds like baffle 'em with bullshit or, I'm clearly so much smarter than you are that you shouldn't even try to argue with me. Lighten up dude.
Got that one too when I've read "why would you use RTTI when you should be using polymorphism instead? Write in plain C if you're going to use C++ that way." [emphasis mine]

Anyway, when A and B discuss with each other, even publicly, C (and C++) should avoid to enter into these discussions IMHO.

Also, not everyone here is a native English speaker, so lighten up.

Bad Sector
07-09-2007, 09:01 AM
@GolfHacker:
I don't really use many static objects. In fact i only use "simple utility objects" as static objects (like vectors, matrices, etc). Most of "big" objects are dynamic objects which i manually allocate. So i don't have problems with accidental object creation.

Also i don't really like "smart pointers" :-P.

Anyway, i don't really do stuff that might fail in a constructor. As i said in my previous post, most of the fail-able stuff is done in a special "init" function or in a createFoo function. I just wish i didn't had to do this wrapping manually.

@Fabio:
Since when C++ is orthogonal? And even if it was, i really prefer to have an additional feature that will save me some code and add a little extra rule instead of not having that feature at all.

Anyway, i admit that i didn't thought about this much, so it's natural to have issues.

On the other hand, it's probably a nice feature to add in UndeadScript, since all objects there are dynamically created ;-)

MedievalElks
07-09-2007, 09:46 AM
I disagree. C++ is just more popular because it is an extension and most compatible with C, which *is* a very good language. C++ is just a monster and some features are plain uglyness (dynamic_cast<bleh>(omg) anyone?).

For what are you using dynamic_cast? That's usually a sign of bad design.

Bad Sector
07-09-2007, 09:54 AM
For what are you using dynamic_cast? That's usually a sign of bad design.

First of all, i completely disagree with those "if you use <feature X> then that's a sign of bad design" responses. Sorry, but to me language features (and even design methodologies) are to be used. Using a feature is not the same as abusing it.

Secondly, i never used the "dynamic_cast" feature. For years now, C-like typecasting is all i needed. In fact, i'm not even sure what's the difference between C's typecasting and dynamic_cast, static_cast or whatever else C++ has.

Third, i mentioned "dynamic_cast" as an example of ugly (according to my taste, at least) C++ syntax. I could mention other stuff instead (like templates).

MedievalElks
07-09-2007, 10:25 AM
First of all, i completely disagree with those "if you use <feature X> then that's a sign of bad design" responses. Sorry, but to me language features (and even design methodologies) are to be used. Using a feature is not the same as abusing it.

That's why I qualified it with "usually".

MedievalElks
07-09-2007, 10:27 AM
Secondly, i never used the "dynamic_cast" feature. For years now, C-like typecasting is all i needed. In fact, i'm not even sure what's the difference between C's typecasting and dynamic_cast, static_cast or whatever else C++ has.


What exactly are you casting? Can you give an example?

Bad Sector
07-09-2007, 12:33 PM
Well, i still disagree with those responses anyway :-P.

What exactly are you casting? Can you give an example?

Eh? I'm referring to any kind of casting. I don't have a trend to cast "X" for "Y" :-P. I use C-style casting wherever i think it will help. I used many kinds of casts, from innocent "char b = (char)yes_its_really_in_char_range_even_if_it_is_a n_int_type" stuff, to more brutal "float foo = *((float*)(byte_array + bar));".

jessechounard
07-09-2007, 01:15 PM
Well, i still disagree with those responses anyway

I think that's just because you don't know (by your admission) what that cast is designed to do.

static_cast - basic conversions (int to char, like your example)
const_cast - removing const-ness, if you know it's safe to do so
dynamic_cast - converting between polymorphically related types
reinterpret_cast - converting between possibly unrelated types

Overuse of dynamic_cast is indeed a potential sign of bad design. I don't think Elks meant that it should never be used, even though it does seem to read that way.

Anyway, since this is off-topic, I'll shut up now. :)

Bad Sector
07-09-2007, 01:50 PM
My statement doesn't hold true only to dynamic_cast, but to any similar response where people are quick to say that something is a bad design only from a single quote someone said. This doesn't happen only here but in many programming-related forums. It's like most people just can get that any language feature can be used for both bad and good.

Here is an example: do you consider goto a bad thing? Would you bash any use of it? If you answered yes to both, see the code below...


/* fictional loadmap function for unknown purposes */
Map *loadMap()
{
XMLParser *parser = new XMLParser();
Map *map = NULL;

if (!parser->load("cool-level.xml")) goto failed;

int mapWidth = parser->root->getIntAttribute("width", 0);
int mapHeight = parser->root->getIntAttribute("height", 0);

if (mapWidth == 0 || mapHeight == 0) goto failed;

map = new Map(mapWidth, mapHeight);

if (!map->loadFromXMLNode(parser->nodeById("mapdata"))) goto failed;

XMLNode *entities = parser->nodeById("entities");
if (!entities) goto failed;

for (XMLNode *node=entities; node; node=node->next)
{
Entity *entity = createEntityByClass(node->getAttribute("class"));
if (entity) map->addEntity(entity);
}

return map;

failed:
if (map) delete map;
if (xml) delete xml;
return NULL;
}


Do you still think that ALL uses of goto are bad?

Well, even if you still think so, that's probably because you're afraid of it :-P.


In any case, at least for me, as long as i know what is done underneath, i don't mind using something that is considered "bad" by others if that something makes my life (and my code) easier.

ilya2
07-09-2007, 01:59 PM
But i would love to have a C++ constructor return NULL :-).

You can overload new... Which wouldn't do that but would be close:

Ex:

struct Foo {
Foo(char*) {}
void *operator new(size_t size) {
return 0;
}
};

int main() {
Foo *bar=new Foo("lala.dat");
if (!bar) return 0;
}


Which would always return 0..

You would probably want to take some parameters:

struct Foo {
Foo(char*) {}
void *operator new(size_t size, bool fail) {
if (fail) return 0; else return malloc(size);
}
};

int main() {
Foo *bar=new(false) Foo("lala.dat");
if (!bar) return 0;
while(1);
}


I guess you could use the overloaded new instead of a constructor for dynamic objects...

GolfHacker
07-09-2007, 05:27 PM
@GolfHacker:
I don't really use many static objects. In fact i only use "simple utility objects" as static objects (like vectors, matrices, etc). Most of "big" objects are dynamic objects which i manually allocate. So i don't have problems with accidental object creation.

An object doesn't have to be static to have a static member function. Just put "static" in front of the member function in the .h file, and you're good to go. Then you just call it like this:

MyClass* myobject = MyClass::instance();

This is equivalent to:

MyClass* myobject = new MyClass();

except that your instance() function is doing some error checking for you and returning NULL if there is a problem (which is what you said you needed).

Also i don't really like "smart pointers" :-P.

Me either. But it is a viable alternative for those who don't mind them.

Anyway, i don't really do stuff that might fail in a constructor. As i said in my previous post, most of the fail-able stuff is done in a special "init" function or in a createFoo function. I just wish i didn't had to do this wrapping manually.

Understood. The static instance() method that I suggested is just a cleaner (IMHO) alternative to your createFoo() function, which might get you closer to what you wanted.

Backov
07-09-2007, 05:56 PM
Do you still think that ALL uses of goto are bad?

Well, even if you still think so, that's probably because you're afraid of it :-P.


In any case, at least for me, as long as i know what is done underneath, i don't mind using something that is considered "bad" by others if that something makes my life (and my code) easier.

Yes, it's bad, and that instance is bad. You used a goto to avoid duplicating 3 lines of code - at worst? In a best case scenario you can lose what's under that label entirely.

jessechounard
07-09-2007, 06:16 PM
I wouldn't design the function quite in that manner, but I acknowledge that it was a made up example, and you might not have either. (And that you weren't looking for a code critique. But for example, if either the new operator or Map's constructor throws an exception, parser's memory is leaked.)

I would have written that function using smart pointers and exceptions. That's a stylistic choice, and I can't say that my method is strictly better than anyone elses. Strangely, I've now sort of gone back on topic. How unusual of me. ;)

But to answer your question, no. I don't think gotos are evil. I think they are generally unnecessary, however. Also, while you might do okay with them, an inexperienced programmer would surely make an unreadable mess using them, and that's why they are taught as off limits.

Bad Sector
07-10-2007, 03:56 AM
@Backov:
I think it's a good use not only because saves me from duplicating these three lines (which could be ten lines, or could be three but need to be duplicated many times and at some point if i need to change a bit the way the cleanup is done, i'll need to modify all of their use - which is a time waste), but also becase in this example it's semantically correct. Goto is cursed because it makes the code difficult to understand, but in this case you just can't go wrong with "goto failed". Also note that "failed" is at the end of the function, nothing hard to find. If this is used exactly the same in many functions (a label named "failed" before the end of the function that performs cleanup and single "goto failed" instructions wherever the function fails), then it becomes something expected and easy to work with.

@jessechounard:
Well my whole point is that i know what's happening in my program (one of the reasons i prefer to stay away from as many 3rd party libraries as possible), so i know that i don't throw exceptions in constructors.

And i'm talking about experienced programmers here.

I want to believe that after 16 years of programming i know where is good to use something and where isn't :-P.