调试断言失败!表达式:__acrt_first_block ==标头 [英] Debug Assertion Failed! Expression: __acrt_first_block == header

查看:190
本文介绍了调试断言失败!表达式:__acrt_first_block ==标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试用GoogleTest编写的dll,当我调用其中一个测试时,它引发了此错误:

I am trying to test the dll which I wrote with GoogleTest and when I call one of the tests It throws me this error:

我得出的结论是问题出在将内存分配给向量,但是我不知道如何解决这个问题,因为我对C ++编程还很陌生。代码如下:

I have come to the conclusion that the problem is in assigning memory to vectors but I don't know how to resolve this as I am fairly new to C++ programming. The code is as follows:

#ArraysCPP11.h
#ifdef ARRAYSCP11_EXPORTS
#define ARRAYSCP11_API __declspec(dllexport)
#else
#define ARRAYSCP11_API __declspec(dllimport)
#endif

__declspec(dllexport) void removeWhiteSpaces(std::vector<std::string> v, std::vector<std::string> &output);



#ArraysCPP11.cpp
void removeWhiteSpaces(std::vector<std::string> v, std::vector<std::string> &output) { //odstranjevanje presledkov iz vector-ja (vsak drugi element je bil presledek)
    for (std::vector<std::string>::iterator it = v.begin(); it != v.end(); it++) {
        std::string buffer = *it;
        if (isdigit(buffer[0])){;
            output.push_back(*it);
        }
    }
}



#TestTemp.h

template<class T> 
class TestTemp
{
public:
   TestTemp();
   void SetValue(T obj_i);
   T GetValue();
   bool alwaysTrue();
   bool TestTemp<T>::formattingTest(std::string input, std::vector<std::string> realVector, std::vector<std::string> formattedInput);
private:
   T m_Obj;
};

template<class T>
inline bool TestTemp<T>::formattingTest(std::string input, std::vector<std::string> realVector, std::vector<std::string> formattedVector) {
std::string input2 = input;
//  std::vector<std::string> fResult;
std::string first;
std::string second;
bool endResult = true;
std::vector<std::string> end;
//std::vector<std::string> result = split(input2, ' ');
removeWhiteSpaces(formattedVector,end);
std::vector<std::string>::iterator yt = realVector.begin();
for (std::vector<std::string>::iterator it = end.begin(); it != end.end(); it++, yt++) {
    first = *it;
    second = *yt;
    if (first.compare(second) != 0) {
        endResult = false;
        break;
    }
}
return endResult;
}



   #ArraysCPP11-UnitTest.cpp
struct formattingTesting{
   //   formattingTesting* test;
   std::string start;
   std::vector<std::string> endResult;
   formattingTesting() {
   }
   explicit formattingTesting(const std::string start, const std::vector<std::string> endResult)
    : start{start}, endResult{endResult} 
   {
   }
};

struct fTest : testing::Test {
   formattingTesting* test;
   fTest() {
      test = new formattingTesting;
   }
   ~fTest() {
      delete test;
   }
};

struct format {
   std::string start;
   std::vector<std::string> end;
};

struct formTest : fTest, testing::WithParamInterface<format> {
   formTest() {
      test->start = GetParam().start;
      test->endResult = GetParam().end;
   }
};

TEST_P(formTest, test1) {
   bool endResult = true;
   TestTemp<int> TempObj;
   std::string first;
   std::string second;
   //std::string start ("1  2 3 4 5 6 7 8 9 10");
   //std::vector<std::string> end = { "1","2","3","4","5","6","7","8","9","10" };
   std::vector<std::string> start2 = { "1","","2","3","4","5","6","7","8","9","10" };
   std::string start = GetParam().start;
   std::vector<std::string> end = GetParam().end;
   bool result = TempObj.formattingTest(start,end,start2);      
   EXPECT_TRUE(result);
}

INSTANTIATE_TEST_CASE_P(Default, formTest, testing::Values(
   format{ "1", {"1"} },
   format{ " ", {} },
   format{ "1 2 3 4 5",{"1","2","3","4","5"} },
   format{ "1  2 3 4 5  6", {"1","2","3","4","5","6"} }
));


int main(int argc, char** argv)
{
   testing::InitGoogleTest(&argc, argv);
   RUN_ALL_TESTS();
   return 0;
}


推荐答案

由于这是DLL,问题可能出在用于分配和释放的不同堆中(尝试静态构建库并检查是否可以运行)。

As this is a DLL, the problem might lie in different heaps used for allocation and deallocation (try to build the library statically and check if that will work).

问题在于,DLL和模板不太同意。通常,根据MSVC运行时的链接,如果在可执行文件中分配了内存,并在DLL中释放了内存,反之亦然(因为它们可能具有不同的堆),这可能是个问题。使用模板很容易发生这种情况,例如:将push_back()推送到DLL中removeWhiteSpaces()内部的向量,因此将向量内存分配到DLL内部。然后,您在可执行文件中使用输出向量,一旦它超出范围,它就会被释放,但是在可执行文件内部,其堆对分配的堆一无所知。砰,你死定了。

The problem is, that DLLs and templates do not agree together very well. In general, depending on the linkage of the MSVC runtime, it might be problem if the memory is allocated in the executable and deallocated in the DLL and vice versa (because they might have different heaps). And that can happen with templates very easily, for example: you push_back() to the vector inside the removeWhiteSpaces() in the DLL, so the vector memory is allocated inside the DLL. Then you use the output vector in the executable and once it gets out of scope, it is deallocated, but inside the executable whose heap doesn't know anything about the heap it has been allocated from. Bang, you're dead.

如果DLL和可执行文件使用相同的堆,则可以解决此问题。为了确保这一点,DLL和可执行文件都必须使用动态MSVC运行时-因此请确保两者均动态链接到运行时,而不是静态链接。特别是,exe文件应与/ MD [d]编译并链接,库也应与/ LD [d]或/ MD [d]链接,而与/ MT [d]都不相关。请注意,此后将要运行该应用程序的计算机将需要运行MSVC运行时库(例如,通过为特定的MSVC版本安装 Visual C ++ Redistributable)。

This can be worked-around if both DLL and the executable use the same heap. To ensure this, both the DLL and the executable must use the dynamic MSVC runtime - so make sure, that both link to the runtime dynamically, not statically. In particular, the exe should be compiled and linked with /MD[d] and the library with /LD[d] or /MD[d] as well, neither one with /MT[d]. Note that afterwards the computer which will be running the app will need the MSVC runtime library to run (for example, by installing "Visual C++ Redistributable" for the particular MSVC version).

即使使用/ MT,您也可以使它工作,但这更加困难-您需要提供一些接口,该接口也允许将在DLL中分配的对象也重新分配在那里。例如类似

You could get that work even with /MT, but that is more difficult - you would need to provide some interface which will allow the objects allocated in the DLL to be deallocated there as well. For example something like:

__declspec(dllexport) void deallocVector(std::vector<std::string> &x);

void deallocVector(std::vector<std::string> &x) {
    std::vector<std::string> tmp;
    v.swap(tmp);
}

(但是,这在所有情况下均不能很好地工作,因为这需要被显式调用,因此不会被调用,例如在发生异常的情况下-要正确解决此问题,您需要提供DLL的某些接口,该接口将覆盖底层的向量,并会考虑适当的RAII)

(however this does not work very well in all cases, as this needs to be called explicitly so it will not be called e.g. in case of exception - to solve this properly, you would need to provide some interface from the DLL, which will cover the vector under the hood and will take care about the proper RAII)

编辑:最终解决方案实际上是拥有所有项目(exe,dll以及整个googleTest项目)内置于多线程调试DLL(/ MDd)
(GoogleTest项目默认内置于多线程调试(/ MTd)中)

EDIT: the final solution was actually was to have all of the projects (the exe, dll and the entire googleTest project) built in Multi-threaded Debug DLL (/MDd) (the GoogleTest projects are built in Multi-threaded debug(/MTd) by default)

这篇关于调试断言失败!表达式:__acrt_first_block ==标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆