What are the realistic outcomes of programmer bugs pertaining to pointers?
What 'bad effects' happen when programmers create pointer bugs?
Practical examples with code are preferable.
What are the realistic outcomes of programmer bugs pertaining to pointers?
What 'bad effects' happen when programmers create pointer bugs?
Practical examples with code are preferable.
Things that can go wrong when pointers are misused:
Memory leaks - You allocate a pointer in a method and then let it go out of scope without properly deallocating it. The pointer to the memory on the heap is now lost, but the memory remains allocated. Freeing this memory is now extremely difficult. More info from Wikipedia.
Access violations - You create a pointer that points at a memory address that you do not have access to, or that does not exist. Pointers are just integers afterall, and can be manipulated like any other number. When you attempt to dereference your invalid pointer, your program will halt. More info from Wikipedia.
Null pointer errors - This is a special case of an access violation. The proper way to "park" a pointer, so that it doesn't point at anything in particular, is to set its value to zero or null. Attempting to dereference a null pointer will halt your program. More info from Wikipedia.
Buffer overflows - You allocate a pointer for a character buffer of 30 characters. You then proceed to stream user input (from a socket, file, console, etc.) into this buffer. If you fail to properly implement buffer bounding checks, then your program could potentially put more than 30 characters into the buffer. This will corrupt any data stored adjacent to the buffer in memory and possibly expose you to a malicious code attack. More info from Wikipedia.
Memory corruption - A pointer is just an integer that contains the memory address of something it points to. As an integer, pointer arithmetic can be used to manipulate the pointer's value in all sorts of interesting ways. Subtle bugs can develop if the pointer calculations go wrong. The pointer will now point to some unknown location in memory, and anything could happen when it is dereferenced.
Null-terminated string problems - These bugs occur when string library functions that expect null-terminated strings are fed character pointers that are not null terminated. The string library functions will continue to process characters, one at a time, until a null is found -- wherever that may be. A joke best illustrates this bug.
It all boils down to accessing memory areas not designated for it. Reading/writing outside allocated area, dereferencing uninitialized pointers. That's basically it.
There's also misinterpreting type of the object pointed to, but this normally takes some effort to get away with without getting yelled at by compiler.
And memory leaks, but that's different story, it's about allocation, not pointers per se.
Just initializing your pointer variables and good clean up will eliminate 99% of your problems. By good clean up, I mean; deallocating memory and setting pointer variables to null.
Otherwise, you need a clear design regarding passing pointers around and what code is responsible for cleaning up that memory. If you end up in a situation where you don't know what code will be the last to use the memory & should be cleaning up, then you've got a design smell, which you'll want to fix in order to maintain your sanity.
Use static analysis tools like Splint.
Most important: Use dynamical analysis tools - they often alert of incorrect use of pointers, breaking array boundaries, etc' I make sure to have zero errors on those, even if the program seems to be working...
The results when dereferencing a bad pointer are undefined, so by definition Anything can happen when you mess up with a pointer. This is why you should avoid using them when at all possible.
The C-ish languages are designed around the use of pointers, and they are dominant right now, so this going to sound like crazy advice to some. I'd advise folks to look into languages that are designed to minimize pointer use and check for common errors, like Ada.
My favorite pointer anectode is the following: I was once working for a group in Florida that maintained a networked flight simulation of 3 heliocpoters at Kurtland AFB in New Mexico (most of the way on the other side of the continent). There was a crash bug that popped up one day. The local site tech couldn't fix it, so after a month or so, one of our engineers got flown over to look at it. Two weeks later he was flummoxed, so another got pulled in. After another month our top engineer got flown over to help too.
One more month later (all the time with the company paying for 3 people living in Hotels, renting cars, and flying back every couple of weekends), they tracked down the problem. It turned out that somebody was indexing one past the end of an array (C has no index checking either). They were then grabbing the crap sitting at that location, passing it to a second machine over the network, and it was using that value as an array index. Since that code was also in C, again no checking. It grabbed the crap at that location and sent it to a third machine. That machine used the crap as a pointer and tried to dereference it. boom.
So a bug in the code on one machine was causing a crash two machines removed down the network. Thousands of dollars and several months of precious time were wasted tracking it down. All because they used a language with no range checks.
I don't know if you can still do that, but I remember a few years ago when we would do a script to crash a system by wiping out its whole RAM. Here is the way we did it.
int *i;
while(1){
*i = 0;
i++;
}
At least that's how I remember we did it. I believe it won't work now though.
Raw pointers are evil. It's no way to know if they are valid or not (dangling pointers), if they have been initialized (if not set to NULL on initialization they may appear as actually pointing to something) and it's very unclear who has the responsibility of freeing the resources they point to (e.g. the caller retrieving or the function returning a pointer).
I wouldn't live a day without smart pointers. std::auto_ptr when I'm transferring ownership (be clear about responsibility), boost::shared_ptr when ownership is shared, boost::weak_ptr when someone only is "observing" the resource.
The best practice is to avoid using pointers as much as possible. Use a managed language instead for the bulk of your software, and only fall down to C for small parts where this is necessary for accessing system resources or efficiency. In other words, C should be regarded much the same as assembly language.
(The original question I helped close as 'not a real question' was quite different and too broad to be useful.)