C++ 为什么用project而不是lib编译gtest

C++ 为什么用project而不是lib编译gtest,c++,compilation,linker,googletest,C++,Compilation,Linker,Googletest,解释gtest必须与project一起编译,而不是使用具有lib和header的标准方法。他们解释说,使用lib可能与“一个定义规则”相冲突。我觉得这个解释很奇怪,因为这是您使用任何其他库的方式,它们与“一个定义规则”不冲突。C++编译器生成的二进制代码可能会因标志、操作系统位的不同而有所不同;此外,不同的编译器可以使用相同的标志生成不同的输出(例如,g++与clang++)。该标准指定了结果行为,但没有指定程序集的每个细节 但这并不是最坏的情况。请看一个例子: SomeHeader.h: #i

解释gtest必须与project一起编译,而不是使用具有lib和header的标准方法。他们解释说,使用lib可能与“一个定义规则”相冲突。我觉得这个解释很奇怪,因为这是您使用任何其他库的方式,它们与“一个定义规则”不冲突。

C++编译器生成的二进制代码可能会因标志、操作系统位的不同而有所不同;此外,不同的编译器可以使用相同的标志生成不同的输出(例如,g++与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\u W\u CHAR\T。在每个项目中,你都有字母的定义,但在一个项目中,它是不同的。编译器不会将有关结构大小的信息添加到其id中。它可能会编译,但在大多数情况下,行为是未定义的。如果您将在一个项目中为字母(字母*pLetter=new字母)分配内存,而在另一个项目(具有不同的定义)中取消分配内存,您将得到堆损坏错误

这当然是可能发生的可能性之一


你提到了其他图书馆。您可能是VS的windows dll/lib?(在linux上,大部分时间都是从源代码编译所有内容)。请注意,它们始终是为工具集的特定实例提供的。因为这个原因。同样在Windows上,共享二进制代码也不像在linux上那样复杂。

我认为谷歌的文档很好地解释了:

每个用户都需要使用相同的编译器标志编译他的测试 用于编译已安装的Google测试库;否则他可能会 遇到未定义的行为 为什么?因为C++有一个叫做一个定义规则的东西:如果两个 C++源文件包含不同的定义 类/函数/变量,并将它们链接在一起,则违反 规则

一个简单(但不准确)的例子:

//动态1.h

int GetInt();
//动态1.cpp

static int i = 1;
int GetInt()
{
  return i;
}
//动态C2.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;
}
//生成主

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的输出因不同的link命令而不同。如果将所有文件编译在一起,链接器可以捕获错误


如果您只是将Gtest链接为一个库,您可能会得到相同的意外行为。

除了通常的调试/发布和32位/64位设置外,Google Test还有很多设置可以控制其行为。例如,它可以从C++11标准(
)中指定的位置,在早期的TR1(
)中使用
元组(
),或者根据平台(即操作系统、编译器和标准库)支持的内容,滚动自己的元组。如果库的二进制编译部分配置为使用自己的
元组
,但代码中包含的部分试图使用标准的
头,那么您就有麻烦了。GoogleTest的特殊之处在于,它旨在实现非常广泛的平台兼容性,因此有大量这样的设置,为冲突创造了大量机会。事实上,在开发人员被大量错误的支持调用淹没之后,这个规则被调用。

你需要澄清你所说的“Project”是什么意思,因为这不是C++术语。在Linux上,我不从源代码中编译所有的东西。当我使用Stand Adt+C++库,QT,无论我如何使用/usr/lib中的lib和/usr/include中的header。问题仍然是,为什么其他库不关注这些事情,而谷歌测试工程师却关注这些事情?所以我理解这个问题,但为什么除了谷歌测试工程师之外,没有人认为这是一个真正的问题?此外,我会在谷歌测试中使用一些已经编译好的版本。只有gtest*.h文件中的ifdef或链接器标志可以改变已经编译好的gtest库的链接,但不知何故,除了谷歌工程师以外的任何人都没有注意到这种可能性。
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()'