开发者

how to check consequence of using free() with new []

A process is crashing with SIGSEV, and the backtraces indicate memory corruption. Valgrind report indicates that there are some 'Mismatched free', i.e memory allocated with new[] is being released with free().

I found the following information from cert.org

Another potential problem is that when passing a pointer to an array allocated with operator new to operator delete(), it is possible that when free() is cal开发者_运维问答led by operator delete() (as is common in many implementations, although not required by the C++ Standard), the pointer passed to free() is not one that was returned by a call to malloc(). This is because the first four bytes returned by malloc() when called by operator new will typically be used to store the size of the array (again, not specified by the Standard, but common), so the pointer returned by operator new actually points to an address that is four bytes from the pointer returned by malloc(). Consequently, free() will read in the wrong size to deallocate, and this could lead to heap memory corruption problems.

Question is, how can I demonstrate that free() is deallocating wrong size? Can anyone suggest how to verify that this is happening in my environment, maybe with gdb or any other tools?

Also, the array is of basic type char, so there is no question of seperate destructor not being invoked.


Question is, how can I demonstrate that free() is deallocating wrong size?

Can anyone suggest how to verify that this is happening in my environment, maybe with gdb or any other tools?

You already ran a tool which told you that this is what is happening. Why would you then run another tool to verify that "this is really what is happening"?

You are mismatching some free calls according to Valgrind. That is problem, and that is what you need to fix.

As long as that problem exists, it might have a million different consequences, one of which is what was described in the text you quoted. But you don't need to know which of this million of consequences is actually happening in your program, because those are just the symptoms, and you already know what the cause is.

The only guaranteed effect when you mismatch free/delete is that "something happens". And what that "something" is? No one can say.

Unless you are intentionally trying to write bad software, you should fix the problem at the source, and what you are asking won't help you with that.


That is implementation defined. You cannot generically 'demonstrate' that, although you might be able to using a specific compiler/toolchain/libc.

I suggest you use valgrind to spot such errors.

More comprehensive lists of such tools can be found on SO

Edit Here is a recomended post with such a list: Problem with memory leak check tools in Linux


You can try using Duma ( http://duma.sourceforge.net/ ). It detects malloc/free new/delete incoherencies. It also checks for double deallocation and modified memory after calling free/delete


The call to free() will not deallocate the wrong size, either the pointer you pass in was allocated with malloc() (or any variant thereof) or it was not. In the first case it will deallocate as much as was initially allocated, while in the second case it will probably crash.

Depending on the implementation the error message that comes with the SIGSEGV will probably tell you that the pointer passed in is invalid (or was not allocated or something alike).


If this is a case of explaining and "demonstrating" this to others, I would suggest you explain why it is dangerous without demonstrating. An explanation should be sufficient in this case to clearly show everyone the pitfalls. If you do insist on demonstrating you could create a buffer using malloc and one using new [] and show the contents of the memory locations that hold the allocated size used with malloc and the contents used by new. Simply observing the difference. But then again the behaviour is implementation specific as sehe explained.


Here is a code sample that demonstrates the issue:

#include <stdlib.h>

struct A
{ int i; };

struct B
{
  ~B(){ }
  int i;
};

int main()
{
  A * a = new A[10];
  free(a);

  B * b = new B[10];
  free(b);
}

If you run that with ltrace under Linux you will see something like:

_Znaj(40, 0x293324, 0x292ff4, 0xbfeaca28, 0x165d35) = 0x88f7008
free(0x088f7008)                                 = <void>
_Znaj(44, 0x293324, 0x292ff4, 0xbfeaca28, 0x165d35) = 0x88f7008
free(0x088f700c

So in the second case the pointer being freed doesn't match the one being allocated (because of the user declared destructor in B).

Of course, a mismatch between new[] and free is undefined behaviour, but it will not always result in SIGSEGVs in practice.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜