|
C/C++ Memory Corruption And Memory LeaksThis tutorial will discuss examples of memory leaks and code constructs which lead to memory corruption. |
|
Related YoLinux tutorials: °C and C++ Dynamic Memory Allocation
Free Information Technology Magazine Subscriptions and Document Downloads
Free Information Technology Software and Development Magazine Subscriptions and Document Downloads
|
There are two forms of Linux Memory accessible to the programmer:
The most obvious memory errors result in a "Segmentation violation" message. This may alert the programmer to the location of the memory error when the program is run in gdb. The following errors discussed are the not so obvious errors. Memory errors:
Memory leak description: Memory is allocated but not released causing an application to consume memory reducing the available memory for other applications and eventually causing the system to page virtual memory to the hard drive slowing the application or crashing the application when than the computer memory resource limits are reached. The system may stop working as these limits are approached.
Many C library functions malloc's memory which MUST be freed: i.e.: strdup(),
Any routine which is supplied by the C libraries or ones written within an application which allocate memory must have the memory freed. Comments on this need should be included in the include file to make users of the function aware of their duties to free the memory and the mechanism by which it is to be freed (free() or delete).
Programmer must free() malloc()'ed memory: Also for calloc(), malloc() and realloc();
Check for memory allocation errors. Can't free it if it didn't get allocated.
Programmer must delete new'ed memory:
Inheritance, polymorphism and the wrong delete:
If you are counting on the destructor to delete memory allocated in the constructor beware of this mistake as it will cause a memory leak. Use a virtual destructor to avoid this problem. The ~BaseClass() destructor is called and then the destructor ~DerivedClass() is chosen and called at run time because it is a virtual destructor. If it is not declared virtual then only the ~BaseClass() destructor is called leaving any allocated memory from the DerivedClass to persist and leak. This assumes that the DerivedClass has extra memory allocated above and beyond that of the BaseClass which must be freed. The same ill effect can be achieved with a C style cast to a class of less scope which will dumb down the destructor to that which may not execute all the freeing of the original class. A C++ style dynamic cast may prevent this error as it will recognize the loss of translation and not allow the cast to take place resulting in a traceable crash rather a tough to find memory leak.
Pointer re-assignment error leads to dangling pointer: If the pointer is re-assigned a new value before being freed, it will lead to a "dangling pointer" and memory leak. Example:
Default copy constructor may not give correct results: Memory allocated by copy constructors for pointer duplication. Check in destructor and delete if necessary. Memory allocated in passing class by value which invokes copy constructor. Also beware, the default copy constructor may not give you the results you want especially when dealing with pointers as the default copy constructor has no knowledge of how to copy the contents of what the pointer points to. To prohibit the use of the default copy constructor define a null assignment operator.
Good practice: Use assert to check pointers before freeing or using:
Memory Corruption: Memory when altered without an explicit assignment due to the inadvertent and unexpected altering of data held in memory or the altering of a pointer to a specific place in memory.
Buffer overflow:
Example 1:
Example 2:
Using an address before memory is allocated and set:
Using a pointer which is already freed:
Freeing memory which has already been freed. Also applies to delete. Freeing a pointer twice:
Freeing memory which was not dynamically allocated:
Incorrect use of delete: The delete must match the use of new. The pairing is new/delete and new [] / delete[]
Do not use malloc()/free() with a C++ class as it will not call the constructor or destructor. Also malloc()/free() can not be mixed with new/delete. i.e. Free() can not be used to free memory allocated with new and delete can not be used to free memory allocated with malloc().
Exception Errors: Freeing memory never allocated. If you use a constructor to allocate memory but an exception is thrown before all is allocated, the destructor needs to be aware that fact or else it may try to free memory which was never allocated. Also the converse is true. If the destructor throws an exception, subsequent steps which free memory may not be executed. This applies to the destructor and all nested destructors which handle/re-throw the exception while the stack unwinds.
Pointer persistence: Function returning a pointer from the stack which can get overwritten by the calling function (in this case main()):
Incorrect passing of a function argument: If the pointer is passed around as an argument and does not get passed correctly, one may try to free the incorrect pointer.
Mixing the object base class and derived class: If mixing the object base class and derived class when passing an object by value as a function parameter, make sure that you understand what may be lost.
Copying an object: Don't use memcpy() or any bit for bit copy function to copy an object. It will not execute the class constructor. What kind of person would do this?? Passing an object in a va_arg() list will result in a bit for bit copy and will not use the default copy constructor.
Related YoLinux Tutorials:
|
|
Return to http://YoLinux.com for more Linux links, information and tutorials
Return to YoLinux Tutorial Index Feedback Form Copyright © 2005 by Greg Ippolito |