Sunday, July 27, 2008

C/C++ - Pitfalls - part II




Memory violations


okay, let's now check a way to really mess things with bad design... Following bug actually demonstrates nastyness of C/C++, it is terribly easy to create numerous annoying bugs, which strike only occasionally. Memory violations. That's a word every C/C++ programmer should be afraid of. No, actually terrified.

Nastynes of memory violations is in the way they emerge. A code can be successfully executed numerous of times, and then suddenly it once crashes. Reason for such behaviour is the way operating system protects memory areas.

When a program is first launched, certain amount of memory is allocated for the process. It is perfectly ok to write/read anywhere inside that allocated memory chunck. Let's now assume we have somehow messed our code so that it writes in random memory location (There's really many ways to actually do this... And I bet every programmer has sometimes done such a bug.) It is fairly possible that our random location happens to be in memory chunck which was allocated for the process' use. So operating system think there was nothing wrong with the write. How ever it may be that we just overwritten some critical information, and that may cause a crash in arbitrary position in the code. Thus locating the real cause is not easy. It may as well be that we managed to write in allocated but unused space. Then it may be that our program completes flawlessly. It may also be that we just wrote in space which was protected by operating system. That will cause instant crash. Unfortunately even if we once can run the program flawlessly, it may well be that it missbehaves, or crashes next time we run it. When you create commercial program, it is not really appreciated amongst customers if your code crashes... And it may do that regardless of carefull testing.

Hence, beware the memory violations.

So let's now see one hideous way to create nasty memory violation...
I once almost did this mistake, but then... A thought stroke my head. How does vector class internally operate? And there's a bug related to this issue in the principle presented in my example below.


vector objvector;
.
.
.
objvector.push_back(obj A);
.
.
objvector.push_back(obj B);
.
.
.
//Create thread with entrypoint void * newthreadfunc(obj *);
// give &objvector[N] as an argument.
.
.
.
objvector.push_back(obj C)
.
.
.


void * newthreadfunc(obj *)
{
//do things
//do more things
//Do something with objvector
return something;
}

So what is the principal fault in this kind of approach?
(Idea was of course to use the same object in both threads, which would have been perfectly ok when correct semaphore protection would have been used. This time it has something to do with vector class' internal operation...).

No comments:

Post a Comment