📄 c-c++ memory corruption and memory leaks.mht
字号:
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>#include <STDLIB.H>
char *textString =3D malloc(128*sizeof(char));
if(textString =3D=3D ENOMEM) ... // Fail!!!!
...
free(textString); // Don't free if allocation failed
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P>Check for memory allocation errors. Can't free it if it didn't =
get=20
allocated.=20
<P>
<HR>
<P><B>Programmer must <TT>delete</TT> <TT>new</TT>'ed memory:</B>=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>using namespace std;
ptr =3D new ClassTypeA;
...
delete ClassTypeA;
</PRE></TD></TR></TBODY></TABLE></DD></DL>New/delete is preferred to=20
malloc()/free() because it can initialize the memory and it =
invokes the=20
constructor for new objects. New/delete also point to the correct =
memory=20
type. Note on mixing source code containing new/delete and=20
malloc()/free(). This is not a problem with the GNU C++ compiler =
but this=20
is not guaranteed for all C++ compilers.=20
<P>
<HR>
<P><B>Inheritance, polymorphism and the wrong delete:</B>=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>BaseClass* obj_ptr =3D new DerivedClass; // =
Allowed due to polymorphism.
...
delete obj_ptr; // this will call the destructor ~Parent() and NOT =
~Child()
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P>If you are counting on the destructor to delete memory =
allocated in the=20
constructor beware of this mistake as it will cause a memory leak. =
Use a=20
virtual destructor to avoid this problem. The ~BaseClass() =
destructor is=20
called and then the destructor ~DerivedClass() is chosen and =
called at run=20
time because it is a virtual destructor. If it is not declared =
virtual=20
then only the ~BaseClass() destructor is called leaving any =
allocated=20
memory from the DerivedClass to persist and leak. This assumes =
that the=20
DerivedClass has extra memory allocated above and beyond that of =
the=20
BaseClass which must be freed.=20
<P>The same ill effect can be achieved with a C style cast to a =
class of=20
less scope which will dumb down the destructor to that which may =
not=20
execute all the freeing of the original class. A C++ style dynamic =
cast=20
may prevent this error as it will recognize the loss of =
translation and=20
not allow the cast to take place resulting in a traceable crash =
rather a=20
tough to find memory leak.=20
<P>
<HR>
<P><B>Pointer re-assignment error leads to dangling pointer:</B>=20
<P>If the pointer is re-assigned a new value before being freed, =
it will=20
lead to a "dangling pointer" and memory leak.=20
<P>Example:=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>char *a =3D malloc(128*sizeof(char));
char *b =3D malloc(128*sizeof(char));
b =3D a;
free(a);
free(b); // will not free the pointer to the original allocated memory.
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P>
<HR>
<P><B>Default copy constructor may not give correct results:</B>=20
<P>Memory allocated by copy constructors for pointer duplication. =
Check in=20
destructor and delete if necessary. Memory allocated in passing =
class by=20
value which invokes copy constructor. Also beware, the default =
copy=20
constructor may not give you the results you want especially when =
dealing=20
with pointers as the default copy constructor has no knowledge of =
how to=20
copy the contents of what the pointer points to. To prohibit the =
use of=20
the default copy constructor define a null assignment operator.=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>ClassA& operator=3D(const ClassA& =
right_hand_side);
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P>
<HR>
<P>Good practice: Use assert to check pointers before freeing or =
using:=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>assert(ptr !=3D0)
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P><A name=3DMEMORYCORRUPTION></A>
<HR>
<TABLE cellSpacing=3D0 cellPadding=3D2 width=3D"100%" border=3D0>
<TBODY>
<TR bgColor=3D#ffcc33>
<TD><B><BIG>Memory =
Corruption:</BIG></B></TD></TR></TBODY></TABLE>
<P><B>Memory Corruption:</B> Memory when altered without an =
explicit=20
assignment due to the inadvertent and unexpected altering of data =
held in=20
memory or the altering of a pointer to a specific place in memory. =
<P>
<HR>
<P><B>Buffer overflow:</B>=20
<P>Example 1: <BR>Overwrite beyond allocated length - overflow.=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>char *a =3D malloc(128*sizeof(char));
memcpy(a, data, dataLen); // Error if dataLen too long.
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P>Example 2: <BR>Index of array out of bounds: (array index =
overflow -=20
index too large/underflow - negative index)=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>ptr =3D (char *) malloc(strlen(string_A)); // =
Should be (string_A + 1) to account for null termination.
strcpy(ptr, string_A); // Copies memory from string_A which is one byte =
longer than its destination ptr.
</PRE></TD></TR></TBODY></TABLE></DD></DL>Overflow by one byte.=20
<P>
<HR>
<P><B>Using an address before memory is allocated and set:</B>=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>struct *ABC_ptr;
x =3D ABC_ptr->name;
</PRE></TD></TR></TBODY></TABLE></DD></DL>In this case the memory =
location=20
is NULL or random.=20
<P>
<HR>
<P><B>Using a pointer which is already freed:</B>=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>char *a =3D malloc(128*sizeof(char));
..
..
free(a);
cout << a << endl; // This will probably work but =
dangerous.
... Do stuff. Probable overwriting of freed memory.
cout << a << endl; // No longer the same contents. Memory =
overwritten by new stuff.
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P>
<HR>
<P><B>Freeing memory which has already been freed. Also applies to =
delete.</B>=20
<P>Freeing a pointer twice:=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
<TD><PRE>char *a =3D malloc(128*sizeof(char));
free(a);
... Do stuff
free(a); // A check for NULL would indicate nothing.
// This memory space may be reallocated and thus we may be =
freeing
// memory we do not intend to free or portions of another =
block of=20
// memory. The size of the block of memory allocated is often =
held=20
// just before the memory block itself..
</PRE></TD></TR></TBODY></TABLE></DD></DL>
<P><B>Freeing memory which was not dynamically allocated:</B>=20
<DL>
<DD>
<TABLE cellSpacing=3D1 cellPadding=3D4 width=3D"100%" =
bgColor=3D#000000=20
border=3D1>
<TBODY>
<TR bgColor=3D#c0c0c0>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -