Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 348
  • Last Modified:

crash when deleting array that was passed to a dll function

i have a dynamically sized array.  It is created and sized within a function. I create and size it as follows:

double *dArray = NULL;
dArray = new double[nSomeSize];

I then pass this array to a dll function, like this:
ptrToDllFunction(dArray);

I then delete the dyanmic array like this:

delete [] dArray;

My program gives the ATTACHED ASSERTION error on the delete line (delete [] dArray):

My best guess is that the Dll function is changed the size of my array argument dArray, so that when I try to delete it after use, I get the error.

Any thoughts?

Thanks very much.


ASSERT-ERROR-1.bmp
0
clintonJ
Asked:
clintonJ
2 Solutions
 
evilrixSenior Software Engineer (Avast)Commented:
Are you allocating the memory in one module/dll and then trying to free it in another? If so this will be your problem. A module/dll can only free heap it has allocated since each module/dll gets its own unique heap. You have to pass the pointer back to the original module/dll to have it freed.
0
 
evilrixSenior Software Engineer (Avast)Commented:
Allocating and freeing memory across module boundaries
http://blogs.msdn.com/oldnewthing/archive/2006/09/15/755966.aspx
0
 
clintonJAuthor Commented:
>> Are you allocating the memory in one module/dll and then trying to free it in another?

No.  Sorry I wasn't clear on that.  I'm deleting the array in the same function in which I create it.  And as far as I know, the dll is NOT changing the size of the array.  It is simply filling it up with contents.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
evilrixSenior Software Engineer (Avast)Commented:
>> Sorry I wasn't clear on that.

That's ok :)


>> I'm deleting the array in the same function in which I create it.
Ok, that's good.

>> And as far as I know, the dll is NOT changing the size of the array.  It is simply filling it up with contents.
Is the DLL your code or 3rd party? What's the function signature of the function you call? Can you show some code (real code, not just an example as example often lie)?
0
 
evilrixSenior Software Engineer (Avast)Commented:
BTW: Your code isn't exception safe in terms of if an exception is throw you have to catch it, clean up and rethrow. You can save yourself a whole load of grief by using a vector rather than new [] and delete [], even if the function expects a double *

std::vector<double> vd(nSomeSize);
double *dArray = &vd[0];
ptrToDllFunction(dArray);

Use dArray  as normal, as long as vd is in scope and you've not called any non-const function on the vector you have a competely contiguous blob of memory just as if it'd been allocated using new[] but you don't need to delete [] it because the vectors destructor will take care of all this for you, making the code clean, tidy and (most important) exception safe. One caveat, you CANNOT use this if dArray has delete [] called on it in any other functions you pass it too. Of course, as long as you know this isn't the case this is completely safe and totally portable.

0
 
jkrCommented:
Can you try to set your build settings to "Use Runtime Library: Multithreaded DLL" and see if the same still happens?
0
 
itsmeandnobodyelseCommented:
>>>> And as far as I know, the dll is NOT changing the size of the array.  

Arrays allocated with C++ new operator cannot be resized. Only pointers allocated using malloc or calloc can be resized by calling realloc.

If a dll would call realloc on a pointer allocated by operator new, it may work in the dll cause in VC6 (and still in later versions of VC compiler) the operator new finally would call malloc. Hence, the realloc in the dll has a chance to succeed. BUT, later in the main application it will give an assertion or a crash or both if either the realloc had returned a new address because there was not enough  free space behind the buffer you allocated (A), or - what is very much likely if the dll function makes a realloc - has still the same pointer but has written beyond the boundaries you had allocated (B).

(A) will assert and crash, cause your pointer already was freed by the realloc and your call to delete operator won't find an allocation for that pointer.
(B) will assert in Debug Mode cause the debugger had allocated some more space than requested and has written some marking bytes at end of the array (no_mans_land area). If the dll function wrote some data to that area the debugger will find that out at delete time and throws an assertion.

The assertion you posted seems to indicate case A as it complains that the pHead->nBlockUse was 0 (an assert statement fails if the expression evaluates to FALSE or 0) what probably is because the the original pointer already was freed and therefore the number of blocks used was reset to 0.

>>>> ptrToDllFunction(dArray);

Can you post the full signature of the dll function (if you don't have the source)?

Normally a function which takes a pointer to an array as an argument needs a second argument that specifies the size of the pointer. If not, it is either not well-defined or it expects some terminating array element, e. g. you pass ten doubles different to zero and finally a zero. Then the dll function could find out that the original size was 11 elements. But it never may resize the pointer given beside it wasn't a double* but a double*& what is a reference to a pointer to double. Then, a pointer could be *returned* by the dll function and the pointer you have passed in was overwritten by the function (your pointer now points to a memory leak which couldn't be freed by anyone). If so, the assertion is for quite another reason. It is cause you want to delete a pointer allocated in the dll which probably has a different heap manager. So, your own heap manager doesn't know of that allocation and that's why it asserts.

If I am right you easily can check that by looking at the pointer address before and after call. If it changed it is either a realloc (waht would be extremely bad by the dll function) or it is a double*& as argument type. In the latter case you don't need an own allocation but simply pass a (NULL) pointer. And you also may not delete the pointer cause it probably was a pointer to some static buffer which may not be deleted.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now