C++ and games programming: the Wesnothian Approach
Moderator: Forum Moderators
Hehe, this is exactly what I am giving to my students and when they became frustrated (You can't lowered me mark only because I missed that one semicolon!) i answer that lowered mark today may save them a lot of frustration tomorrowaelius wrote:- b.Code: Select all
for(int i=1; i < 10; i++); { ...a bunch of stuff... }
One stupid thing I did several times in one form or another was using wrong types, like this:
There was often something like this hidden deep in other code, and I think the time I spent hunting such stuff amounts to days. If just g++ would spit out a warning
And one other very embarassing thing for me is when I forget to initialize some class members, as I already mentioned. Usually I have one constructor who intializes everything, and maybe some others who do too, and just one of them forgets one variable. The program might now run fine a lot of times (since the variable got sane values), just sometimes it doesn't work since the varaible has wrong values. This one is by far my number one time consuming bug (probably because I'm used to C, where you allocate with calloc and therefore everything is initialized to 0).
Code: Select all
unsigned int r = 1;
float x = 10;
x = x + (r - 2);
There was often something like this hidden deep in other code, and I think the time I spent hunting such stuff amounts to days. If just g++ would spit out a warning
And one other very embarassing thing for me is when I forget to initialize some class members, as I already mentioned. Usually I have one constructor who intializes everything, and maybe some others who do too, and just one of them forgets one variable. The program might now run fine a lot of times (since the variable got sane values), just sometimes it doesn't work since the varaible has wrong values. This one is by far my number one time consuming bug (probably because I'm used to C, where you allocate with calloc and therefore everything is initialized to 0).
When you have something like the error that happens here, which is an unsigned int going out of the bounds of what it is supposed to hold, what is supposed to happen?allefant wrote:One stupid thing I did several times in one form or another was using wrong types, like this:
Code: Select all
unsigned int r = 1; float x = 10; x = x + (r - 2);
There was often something like this hidden deep in other code, and I think the time I spent hunting such stuff amounts to days. If just g++ would spit out a warning
Is this defined anywhere in the standard?
No, the behavior of integer overflow is explicitely described by the standard: it is undefined. If a detail of the language is present in the standard, it falls into one of these three categories: defined, implementation-defined, undefined. What you have described is an implementation-defined feature. But integer overflow is undefined. As a consequence, for MIN_INT - x, the answer is 42, and sorry for the inconvenience.torangan wrote:For int there's no definition by the standard (assuming MIN_INT - x) and the result does depend on the compiler / architecture / optimization level...
More seriously, "undefined" features are useful for compiler designer. For integer overflows, it means that if you add 1 to a positive integer, the compiler can assume it is still a positive integer. Indeed, either it is a positive integer, either there was an overflow, and an undefined integer could as well be a positive integer. This is incredibly useful when looking for loop invariants when compiling.
Well, I didn't say anything else, did I? I know that it's undefined but that simply means what I wrote. There's no definition in the standard what the result will be. It'll be consistent in a specific situation but there are no guarantees at all once you change architecture, compiler, optimizations... Usually it'll be what your hardware makes out of it but like you wrote, the compiler is free to assume that it'll never overflow while doing optimizations.
Talking in standard terms isn't very usefull to the casual user and especially undefined is somewhat hard to grasp for most users. Obviously it's clearly defined to be undefined but I think - expect the result to be random is the most usefull for the user. It's rather unlikely that it'll cause the program to abort but that would of course be an absolutely correct implementation!
Talking in standard terms isn't very usefull to the casual user and especially undefined is somewhat hard to grasp for most users. Obviously it's clearly defined to be undefined but I think - expect the result to be random is the most usefull for the user. It's rather unlikely that it'll cause the program to abort but that would of course be an absolutely correct implementation!
Stupid mistake:
-- it is about c++ portable Unix/Dos application, got it from "How not to program in C++" book.
Code: Select all
#... includes
#ifdef UNIX
char* path ="/root/newapp/.config";
#elseif MS_DOS
char* path ="\root\newapp\.config";
#endif
int main() {
std::cout<<"Opening config file ...\n"<<
std::ifstream config(path);
if (config.bad()) {
std::cerr << "File not opened! What???\n";
return -1;
}
cout<<"File is opened ...";
return 0;
}
-
- Posts: 209
- Joined: October 27th, 2004, 8:24 am
- Location: New Zealand
No, you don't understand at all what "undefined" means.torangan wrote:I know that it's undefined but that simply means what I wrote. There's no definition in the standard what the result will be. It'll be consistent in a specific situation but there are no guarantees at all once you change architecture, compiler, optimizations...
What you are describing is an "implementation-defined" feature. Consider division by a negative number for example. It is "implementation-defined": the behavior is documented by the implementation. The result will be consistent once you have set the architecture and the compiler (and its options).
Integer overflow is not guaranteed to be consistent. I suggest you read the paragraph 1.3.12 [defns.undefined] of the standard, especially the part that talks about unpredictable results. Contrarily to what you seem to believe, "unpredictable" doesn't mean "consistent", even if you restrict yourself to a specific situation.
There's no gurantee that it'll be consistent for a given situation but it's extremly likely that running the same program with the same input multiple times will have the same result. If not, it's still correct because it's been undefined in the first place but you'd need some rather strange hardware to get completely unpredictable results. I know that the exact definition is even more loose but hardware tends to be somewhat predictable most of the time.
The simple rule is: never invoke undefined behaviour. Reality is: signed integer overflow is considered to be modulo by many programmers.
The simple rule is: never invoke undefined behaviour. Reality is: signed integer overflow is considered to be modulo by many programmers.