Rok*_*Rok 17 c++ visual-studio-2015
我正在尝试测试我用GoogleTest编写的dll,当我调用其中一个测试时它会抛出这个错误:
我得出结论,问题在于为向量分配内存,但我不知道如何解决这个问题,因为我对C++编程很新.代码如下:
#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);
Run Code Online (Sandbox Code Playgroud)
#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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
#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;
}
Run Code Online (Sandbox Code Playgroud)
#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;
}
Run Code Online (Sandbox Code Playgroud)
axa*_*lis 39
由于这是一个DLL,问题可能在于用于分配和释放的不同堆(尝试静态地构建库并检查它是否有效).
问题是,DLL和模板不能很好地协同.通常,根据MSVC运行时的链接,如果内存在可执行文件中分配并在DLL中解除分配,反之亦然(因为它们可能具有不同的堆),则可能会出现问题.这很容易发生在模板上,例如:push_back()到DLL中removeWhiteSpaces()内的向量,因此向量内存在DLL内部分配.然后在可执行文件中使用输出向量,一旦它超出范围,它就会被释放,但在可执行文件中,其堆不知道有关它已分配的堆的任何内容.砰,你死了.
如果DLL和可执行文件都使用相同的堆,则可以解决此问题.为了确保这一点,DLL和可执行文件都必须使用动态MSVC运行时 - 因此请确保它们都动态链接到运行时,而不是静态链接.特别是,exe应该与/ MD [d]和带有/ LD [d]或/ MD [d]的库一起编译和链接,两者都没有/ MT [d].请注意,之后运行应用程序的计算机将需要运行MSVC运行时库(例如,通过为特定的MSVC版本安装"Visual C++ Redistributable").
你甚至可以使用/ MT来完成这项工作,但这更加困难 - 你需要提供一些接口,允许在那里释放DLL中分配的对象.例如:
__declspec(dllexport) void deallocVector(std::vector<std::string> &x);
void deallocVector(std::vector<std::string> &x) {
std::vector<std::string> tmp;
v.swap(tmp);
}
Run Code Online (Sandbox Code Playgroud)
(但是这在所有情况下都不能很好地工作,因为这需要显式调用,因此不会被调用,例如在异常的情况下 - 为了正确解决这个问题,你需要提供一些来自DLL的接口,它将覆盖引擎盖下的矢量将照顾正确的RAII)
编辑:最终的解决方案实际上是在多线程调试DLL(/ MDd) 中构建所有项目(exe,dll和整个googleTest项目)(GoogleTest项目是在多线程调试(/ MTd)中构建的) 默认情况下)
我在使用 Microsoft Visual Studio 2019 时遇到了同样的问题,只需将“运行时库”更改为“多线程调试 DLL (/MDd)”即可解决
右键单击“解决方案资源管理器”->“属性”->“C/C++”->“代码生成”上的解决方案,然后将“运行时库”更改为“多线程调试 DLL (/MDd)”