设置多线程调试(/MTd)(C ++)时发生崩溃

设置多线程调试(/MTd)(C ++)时发生崩溃

问题描述:

在构建动态库(使用C ++)时,我们可以选择Windows的多线程调试(/MTd)或多线程调试DLL(/MDd)运行时库.如果选择多线程调试",则创建的动态库将负责该库中使用的所有变量的内存分配.因此,下面的示例将显示一种情况,其中/MDd设置将起作用,而/MTd设置将失败:

When building a dynamic library (in C++), we can select Multi-threaded Debug (/MTd) or Multi-threaded Debug DLL (/MDd) run time library for Windows. If we select Multi-threaded Debug, then the created dynamic library will be in charge of memory allocation for all the variables that are used in the library. Therefore, the following example will show a case where /MDd setting will work while /MTd setting will fail:

my_dll.h

 class MY_EXPORT DllClass
    {
    public:

       std::vector<int> abcWorkable;


       void create_new_input_workable();

    };

my_dll.cpp

my_dll.cpp

void DllClass::create_new_input_workable()
{
    abcWorkable.push_back(3);
    abcWorkable.push_back(4);
}

main.cpp

int main(void)
{
    DllClass mine;
 //mine.abcWorkable.reserve(20);
     mine.create_new_input_workable();       

    return 0;
}

有两种解决此问题的方法:一种是使用静态库而不是动态库,另一种是仅在动态库或可执行文件中分配内存,例如,如果我们更改main.cpp:

There are two work-around solutions to this problem: one is using static library rather than the dynamic one and the other is to allocate memory only in the dynamic library or the executable, for example if we change main.cpp:

int main(void)
    {
        DllClass mine;
       mine.abcWorkable.reserve(20);
         mine.create_new_input_workable();       

        return 0;
    }

此时变量 std :: vector< int>abcWorkable 在可执行程序中分配了内存.但是,如果类(在dll中)内部的变量难以在可执行文件中分配内存,则此解决方案可能会失败.我还举另一个例子:

It will work as this time the variable std::vector<int> abcWorkable is allocated memory in the executable program. However, if the variable insider the class (in the dll) is difficult to allocate memory in the executable, then this solution may fail. I also take another example:

my_dll.h

class MY_EXPORT DllClass
{
public:
   std::list<std::vector<int> > myContainer;

   void create_new_input();
}

my_dll.cpp

my_dll.cpp

void DllClass::create_new_input()
{
  std::vector<int> abc;
  abc.push_back(2);
  abc.push_back(3);
  myContainer.push_back(abc);

}

main.cpp

int main()
{
 DllClass mine;
mine.create_new_input();

std::list<std::vector<int> >::iterator it = mine.myContainer.begin();
std::list<std::vector<int> >::iterator itEnd = mine.myContainer.end();
while(it != itEnd)
{
    for(int i=0; i<(*it).size(); i++)
        std::cout<<(*it)[i]<<std::endl;
    it++;
}
return 0;
}

不可能事先为变量 std :: list< std :: vector< int>分配内存.>myContainer ,那么我的问题是如何处理这种情况?(除了使用静态库)谢谢.

It is impossible to allocate memory before hand for the variable std::list<std::vector<int> > myContainer, then my question is how I can deal with this situation? (Except using static library) Thanks.

使用/MT进行构建时,每个模块都会拥有自己的CRT副本.具有其自己的全局变量(如 errno )和其自己的使用自己的堆的内存分配器.最终程序将与多个CRT副本一起运行.

When you build with /MT then every module will have its own copy of the CRT. With its own global variables like errno and its own memory allocator that uses its own heap. The final program will run with multiple CRT copies.

这非常麻烦,特别是对于您的代码.因为您从DLL中按值返回了std :: string.哪个分配在DLL使用的CRT副本的堆上.该对象需要由调用者再次释放.但是它使用 different 堆,并且可能无法释放该对象.卡布姆.

This is very troublesome, particularly with your code. Because you return an std::string by value from the DLL. Which was allocated on the heap that the CRT copy that the DLL uses. This object needs to be released again by the caller. But it uses a different heap and cannot possibly release the object. Kaboom.

在这里使用/MD是一项硬性要求.这样可以确保每个模块都使用相同的CRT副本,并且最终程序中仅存在一个实现.只要它们始终使用相同的CRT版本构建即可.

Using /MD is a hard requirement here. Which ensures that every module uses the same CRT copy and only a single implementation is present in the final program. As long as they were built with the same CRT version anyway.