crash when deleting array that was passed to a dll function

Posted on 2009-04-28
Last Modified: 2012-05-06
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:

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.

Question by:clintonJ
    LVL 39

    Expert Comment

    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.
    LVL 39

    Expert Comment

    Allocating and freeing memory across module boundaries

    Author Comment

    >> 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.
    LVL 39

    Expert Comment

    >> 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)?
    LVL 39

    Accepted Solution

    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];

    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.

    LVL 86

    Expert Comment

    Can you try to set your build settings to "Use Runtime Library: Multithreaded DLL" and see if the same still happens?
    LVL 39

    Assisted Solution

    >>>> 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.

    Featured Post

    Find Ransomware Secrets With All-Source Analysis

    Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

    Join & Write a Comment

    Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
    IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
    The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
    The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

    755 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    23 Experts available now in Live!

    Get 1:1 Help Now