Académique Documents
Professionnel Documents
Culture Documents
0 | Real-time Mantra | Contact Home > Real-time Mantra > Embedded Design > Debugging Software Crashes II
Stack
Memory corruption in the global area, stack or the heap can have confusing symptoms. These symptoms are explored here.
If you have a debugging system which allows you to put breakpoints on data write to a certain location, use that feature to find the offending program corrupting the memory. If you don't have the luxury of such a tool, the following steps might help. If the variable is a part of structure, check if overflow/underflow of previous or next variables in the structure could have caused this corruption. If other structure member access seems harmless, use the linker generated symbol map to locate other global variables declared in the vicinity of the corrupted structure. Examine the data structures to determine if they could have caused the corruption.
Sometimes looking at the corrupted memory locations can also give a good idea of the cause of corruption. You might be able to recognize a string or data pattern identifying the culprit. This might be your only hope if the corruption is caused by an un-initialized pointer. Extent of corruption might also give a clue of the cause of corruption. Try to determine the starting and ending points of a corruption (only possible if the corrupting program is writing in an identifiable pattern).
If a crash is observed in memory management primitives of the operating system, heap corruption is a possibility. It has been observed that memory buffer corruption sometimes leads to corruption of OS buffer linked list, causing crashes on OS code. If a memory corruption is observed in an allocated buffer, check the buffers in the vicinity of this buffer to look for source of corruption. Corruption of buffers close to heap boundary might be due to stack overflow or stack overwrite leading to heap corruption (see the above figure) Conversely, stack corruption might take place if a write into the heap overflows and corrupts the stack area.
If a crash is observed when a function returns, this might be due to stack corruption. The return address on the stack might have been corrupted by
stack operations of called functions. Crash after an interrupt service routine returns might also be caused by stack corruption. Stack corruption can also be suspected when a passed parameter seems to have a value different from the one passed by the calling function. When a stack corruption is detected, one should look at the local variables in the called and calling functions to look for possible sources of memory corruption. Check array and pointer declarations for sources of errors. Sometimes stray corruption of a processors registers might also be due to a stack corruption. If a register gets corrupted due to no reason, one possibility is that an offending thread or program corrupted the register context on the stack. When the register is restored as a part of a context switch, the task crashes. Corruption in heap can trickle down to the stack. Stack overflow takes place when a programs function nesting exceeds the stack allocated to the program. This can cause a stack area or heap area corruption. (Depends upon who attempts to access the corrupted memory first, a heap operation or stack operation).
// Override method
All classes with virtual functions have a pointer to the V-table corresponding to overrides for that class. The V-table pointer is generally stored just after the elements of the base class. Corruption of the v-table pointer can baffle developers as the real problem often gets hidden by the symptoms of the crash. The figure above shows the declaration of class A and B. The figure below shows the memory layout for an object of class B. If m_array array is indexed with an
index exceeding its size, the first variable to be corrupted will be the v-table pointer. This problem will manifest as a crash on invoking method SendCommand. The reason this happens is that SendCommand is a virtual function, so the real access will be using a virtual table. If the virtual table pointer is corrupted, calling this function will take you to never-never land. int m_a int m_array [MAX_ARRAY] VTable *vptr int m_b For more details on v-table organization refer to C and C++ Comparison II article.
Handle out of memory exception Check for new returning a NULL pointer.
Using assert
An ounce of prevention is better than a pound of cure. Detecting crash causing
conditions by using assert macro can be a very useful tool in detecting problems much before they lead to a crash. Basically assert macros check for a condition which the function assumes to be true. For example, the code below shows an assertion which checks that the message to be processed is non NULL. During initial debugging of the system this assert condition might help you detect the condition, before it leads to a crash. Note that asserts do not have any overhead in the shipped system as in the release builds asserts are defined to a NULL macro, effectively removing all the assert conditions. assert usage
void HandleOrigination(const OriginationMsg *pMsg) { assert(pMsg); assert(pMsg->numberOfDigits != 0); . . . }
Home | EventStudio System Designer 4.0 | VisualEther Protocol Analyzer 1.0 | Real-time Mantra | Contact Copyright 2000-2011 EventHelix.com Inc. All Rights Reserved.