Google test documentation解释说gtest必须与项目一起编译,而不是使用lib和header的标准方法。他们解释说使用lib可能会违反一个定义规则"。我发现这个解释很奇怪,因为这是你使用任何其他库的方式,它们与"一个定义规则没有冲突"
答案 0 :(得分:1)
Google Test有许多控制其行为的设置,超出了通常的调试/发布和32位/ 64位的设置。例如,它可以在早期TR1(tuple
)中使用来自C ++ 11标准(<tuple>
)中指定位置的<tr1/tuple>
,或者根据具体内容使用自己的tuple
。平台(即OS,编译器和标准库)支持。如果在二进制文件中编译的库部分配置为使用自己的<tuple>
,但是#include到代码中的部分会尝试使用标准{{1}}标题,那么您就遇到了麻烦。 Google Test的特殊之处在于它旨在实现非常广泛的平台兼容性,因此具有大量这些设置,从而为冲突创造了充足的机会。实际上,在开发人员被那些正在犯这种错误的人的大量支持电话淹没之后,就会引用相关规则。
答案 1 :(得分:0)
C ++编译器根据标志,操作系统位数生成二进制代码。另外,不同的编译器可以使用相同的标志生成不同的输出(例如g ++ vs clang ++)。该标准指定了结果行为,但没有指定汇编的每个细节。
但这不是最糟糕的情况。寻找一个例子:
<强> SomeHeader.h 强>:
#ifdef MY_W_CHAR_T
#define my_char_t unsigned long
#else
#define my_char_t char
#endif
struct letter
{
my_char_t msg[255];
}
现在,您可以拥有多个“项目”(可能类似于VS项目),并且每个项目都可以使用 SomeHeader.h 。更确切地说,除了一个定义 MY_W_CHAR_T 之外的所有内容。在每个项目中,您都有字母的定义,但在一个项目中它有所不同。编译器不会将有关struct size的信息添加到其id。它可能会编译,但在大多数情况下行为是不确定的。如果要在一个项目中为字母( letter * pLetter = new letter )分配内存并在另一个项目中解除分配(具有不同的定义),则会出现堆损坏错误。
这当然是可能发生的可能性之一。
你提到的其他图书馆。 VS你可能是windows dll / lib吗? (在linux上,你可以在大多数时间从源代码编译所有内容)。请注意,它们始终为特定的工具集实例提供。这是因为这个原因。同样在Windows上,在Linux上共享二进制代码并不是那么复杂。
答案 2 :(得分:0)
我认为Google的文档解释得很好:
每个用户都需要使用相同的编译器标志来编译他的测试 用于编译已安装的Google Test库;否则他可能 遇到未定义的行为 为什么?因为C ++有这个叫做单定义规则的东西:如果有两个 C ++源文件包含相同的不同定义 类/函数/变量,并将它们链接在一起,你违反了 规则。
一个简单(但不准确)的例子:
// Dynamic1.h
int GetInt();
// Dynamic1.cpp
static int i = 1;
int GetInt()
{
return i;
}
// Dynamic2.h
int GetInt();
// Dynamic2.cpp
static int i = 2;
int GetInt()
{
return i;
}
// main.cpp
#include "dynamic1.h"
#include "dynamic2.h"
#include <cstdio>
int main()
{
::printf("GetInt returns %d\n", GetInt());
return 0;
}
GetInt()
的预期结果是什么?
这取决于您编译和链接代码或链接顺序的方式。
//编译如此
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp
//生成主
g++ -o main main.cpp -L. -ldynamic1 -ldynamic2
// GetInt returns 1
g++ -o main main.cpp -L. -ldynamic2 -ldynamic1
// GetInt returns 2
g++ -o main main.cpp dynamic1.cpp dynamic2.cpp
// multiple definition of `GetInt()'
注意main的输出因链接命令不同而不同。如果将所有文件一起编译,链接器可以捕获错误。
如果您只是将Gtest链接为库,则可能会出现相同的意外行为。