Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is a scalar deleting destructor being called as a result of vector delete on Windows?

I have a code that is leaking on Windows. It runs fine on many unix platforms and the leak only occurs on Windows. The binary consists of exe, 1 dll and 2 static libs. The exe links to both the dll and the static libs, while the static libs link with the dll as well. The leak occurs in the exe code when instead of calling to a vector deleting destructor, for some reason scalar deleting destructor is called. This results in only the first object in the array to be deleted while the rest of the array stays in memory.

The leaking pseudo-code looks like this:

class MyClassFromExe : public MyBaseClassFromDll {
  public:
    ClassFromDll* m_arr;

    MyClassFromExe(unsigned int size)  
    {
      m_arr = new ClassFromDll[size];
    }

    ~MyClassFromExe() 
    {
      delete [] m_arr;
    }
};

void func()
{
  MyClassFromExe obj(3);
}

When func() finishes and the destructor is called I see that only the destructor of the first object in m_arr is called. From debugger I see that this is done from scalar deleting destructor and not from vector deleting destructor. This explains why only the first object is destroyed. What I need to understand is why scalar deleting destructor is called when delete [] is used???

I found this thread - Why is vector deleting destructor being called as a result of a scalar delete?. I followed the suggestions there and made sure that all the modules are compiled with /MD.

Important to notice that when the dll that contains ClassFromDll was a static library and not a dll, everything worked fine. The leak started only when the static library was changed to be a dll. While the program leaks in Release mode, it crashes in Debug mode on delete [] m_arr. The crash occurs in dbgdel.cpp line 52 - _BLOCK_TYPE_IS_VALID(pHead->nBlockUse).

On unix platforms this lib is also a shared lib and as expected vector deleting destructor is called there and there is no leak. Could the problem be with the VC compiler? Or maybe some other settings of the projects need to be changed? I'm using VC2003.

Thank you in advance!

like image 986
noplk Avatar asked Feb 09 '11 17:02

noplk


2 Answers

This is an old Problem in VC++ regarding DLLs and Object-Arrays. The cause is an incorrect compiler optimization as explained by Microsoft.

http://support.microsoft.com/kb/121216/en-us

Better use the STL-containers which dont have the problem due to the use of allocator.

like image 71
Markus Kull Avatar answered Nov 16 '22 02:11

Markus Kull


A class in a DLL is extremely touchy, without much help from compilers. Check out this answer for details WHY this is problematic: How can I call a function of a C++ DLL that accepts a parameter of type stringstream from C#?.

Short version: if the class interface uses ANY inlined code, you will experience potential problems exactly like this. Any templated object (such as std::string) included.

I would guess this is why. It is similar to the problem @Mikael Persson suggests.

like image 44
tenfour Avatar answered Nov 16 '22 01:11

tenfour