c++dllheap-corruptionxll

Why do I get a Heap Corruption when resizing a vector from inside a dll?


I am writing a XLL (using XLW library) that calls a DLL function. This DLL function will get a vector reference, modify the vector and return it by argument.

I have a VS10 solution with several c++ projects, some DLLs and a XLL that will call DLL functions from excel. I compiled everything using VS10 compiler, with _HAS_ITERATOR_DEBUGGING=0 and _CRT_SECURE_NO_WARNINGS and used same runtime library (/MDd) for all projects.

I also had to rebuild the XLW library to comply with _HAS_ITERATOR_DEBUGGING=0 that I have to use in my projects.

When calling the xll_function I was getting Heap Corruption errors and couldn't figure out why. After I tried resizing my vector before calling the dll function the error was gonne. That is, I can call the function and get the right vector returned by argument and no heap corruptions.

Could someone shed some light on this? As I am new to using DLLs I'm not sure if this should happen or if I am doing something wrong.

As you can see in the code below, the dll function will try to resize forwards and that is the point that I think is generating the heap errors. I'm trying to understand why this happens and how this resizing and allocation works for dlls. Maybe I can't resize a vector allocated in another heap.

** Code below - the first function is a static method in a class from a dll project and the second function is exported to the XLL.

void dll_function(double quote, const std::vector<double>& drift, const std::vector<double>& divs, std::vector<double>& forwards)
{
    size_t size = drift.size();
    forwards.resize(size);

    for( size_t t = 0; t < size; t++)
    {
        forwards[t] = (quote - divs[t]) * drift[t];
    }
}


MyArray xll_function(double quote, const MyArray& drift, const MyArray& divs)
{
    // Resizing the vector before passing to function
    std::vector<double> forwards(drift.size());

    dll_function(quote, drift, divs, forwards);

    return forwards;
}

Solution

  • To pass references to std::vector or other C++ collections across DLL boundaries, you need to do following.

    1. Use same C++ compiler for both modules, and same version of the compiler.

    2. In project settings, set up same value to the setting General / Platform Toolset.

    3. In project settings, set up C/C++ / Code Generation / Runtime Library value to “Multi-threaded DLL (/MD)”, or Multi-threaded Debug DLL (/MDd) for debug config. If one of the projects have a dependency which requires static CRT setting, sorry you’re out of luck, it won’t work.

    4. Use same configuration in both sides: if you’ve built debug version of the DLL, don’t link with release version of the consuming EXE. Also don’t change preprocessor defines like _ITERATOR_DEBUG_LEVEL or _SCL_SECURE_NO_WARNINGS, or if you did, change them to the same value for both projects.

    The reason for these complications, C++ doesn’t have standardized ABI. The memory layout of std::vector and other classes changes based on many things. Operators new and delete are also in C++ standard library, i.e. you can’t allocate memory with C++ in one module, free in different one.

    If you can’t satisfy these conditions, there’re several workarounds, here’s a nice summary: https://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL