链接失败:同一文件中函数之间的ABI冲突



我不明白这怎么可能发生。在g++中,我得到一个错误,在相同的ABI指令下,在同一文件中同时定义的两个例程之间存在ABI冲突。由于未知的原因,链接器正在搜索一个函数的c++ 11版本,尽管我非常小心地告诉它不要使用c++ 11版本的任何东西,在我的makefile中最后一次调用g++。

下面是makefile的相关块-在包含任何内容之前使用_D_GLIBCXX_USE_CXX11ABI=0。所有其他.o文件都以同样的方式构建。

project: chrome.o critter.o gene.o loc.o mask.o main.o octree.o rng.o save.o test.o utils.o
g++ -std=c++17 -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -lm -Wall -o project chrome.o critter.o gene.o loc.o mask.o main.o octree.o rng.o save.o test.o utils.o
main.o: main.cpp main.h save.h utils.h gene.h chrome.h critter.h
g++ -std=c++17  -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -c -Wall -o main.o main.cpp 

这是相关的源代码块。

// the makesave method returns a string which is to be written to a savefile.
std::string rundata::makesave() const { // save all data
std::string parmsave = rparms.save2string();
std::string genesave = genes.makesave();
std::string chromesave = chromes.makesave();
std::string crittersave = critters.makesave();
return("<rundata> "+ parmsave + genesave + chromesave + crittersave + " </rundata>n");
}

// the saveData method opens and writes the savefile.
void rundata::saveData(){
FILE *sav = fopen(rparms.savename(), "w");
if (sav == NULL) {fprintf(stderr, "Error opening save file to write.n"); exit(1);}
std::string outstr = makesave();
fwrite(outstr.data(), 1, outstr.size(), sav);
fclose(sav);
}

下面是我运行make:

的结果
albert@juno:~/src/nevermind$ make
g++ -std=c++17  -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -c -Wall -o main.o main.cpp 2>&1 |  head -20
g++ -std=c++17 -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -lm -Wall -o nevermind chrome.o critter.o gene.o loc.o mask.o main.o octree.o rng.o save.o test.o utils.o 2>&1 | head -20
/usr/bin/ld: main.o: in function `rundata::saveData()':
main.cpp:(.text+0x2ac): undefined reference to `rundata::makesave[abi:cxx11]()'
collect2: error: ld returned 1 exit status

这不是由于在包含库之前未能使用宏而导致的对错误版本库函数的调用:这是对在同一文件中定义的函数的调用,在同一时间编译,使用相同的ABI指令。我和ABI有冲突吗!

这怎么可能?

使用g++编译c++代码时,需要做三件事才能完全指定语言。

-std=c++17告诉你源代码是什么样子的,或者是什么意思。

-D_GLIBCXX_USE_CXX11ABI=0告诉编译器不要调用ABI与c++ 11版本当前ABI兼容的库函数。

-fabi-version=14告诉它为它生成的机器码使用最新的ABI。

这是我错过的最后一件事。我让它自由决定使用什么二进制ABI作为输出,即使它是用-std=c++17作为输入编译的。出于某种原因,我仍然不明白,它做出了一个绝对错误的选择。但是如果我命令它使用最新的ABI,它就不能自由地做出这个选择了。

我可能永远不知道为什么编译器做了它所做的事情,但至少我知道如何确保它不再这样做。

最新更新