1

我不是任何语言或 GCC 的专家。所以我的问题可能低于标准。

我正在使用 GCC 构建一个包含数千个 CPP 文件的代码库。在一个文件中说A.cpp我正在调用B.cpp[B.cpp包含定义的类的类方法定义B.h]中的一些函数。构建没问题。B.o但是后来我从makefile中排除了。所以现在B.o没有创建目标文件。但在这种情况下,我预计在编译或链接阶段会出错,因为A.cpp是从B.cpp. 但是没有,代码仍然没有错误地构建。但是当我将 fn 调用从A.cpp另一个文件移到另一个文件C.cpp时,它给了我一个链接器错误,这是我认为的预期行为。

这是预期的行为吗?我还检查了在构建期间创建的映射文件,其中列出了所有函数名称,并且B.cpp即使没有创建 B.cpp 的目标文件,映射中的函数也存在。所以我的问题是为什么当我从不属于构建的文件中调用函数时没有错误。我尝试从以前的版本中删除所有目标文件和二进制文件以清理可能存在的任何残留物,但无济于事。我没有任何线索。任何人都可以提供一些帮助吗?

在我的地图文件中,普通功能如下所示

80010820 T __gccmain

80010828 t __gccmain_endETC

但是来自 B.cpp 的 fns 被列为

U CNvThread::ProcMsgReq(unsigned, void*)

U CNvDbMgrThread::Singleton(unsigned long)

4

3 回答 3

1

如果B.o之前的版本仍然存在,它将链接到旧副本就好了(除非发生重大变化)。如果您没有构建最终的可执行文件,并且只有A.o,那么这仍然没有问题,因为A.o引用了来自 的函数B,但直到最终的输出文件链接才与它们链接。

同样,如果B.o之前的构建中仍然存在,它将被使用,这就是它出现在地图文件中的原因。

于 2013-01-09T03:55:16.593 回答
1

听起来你有一个“makefile”:很好。

默认情况下,“make”(通常)会尝试构建您的项目。无论如何,这是标准约定。

通常,make 还会有其他“目标”。例如,您可以键入“make clean”或“make cleanall”。如果这些目标存在,它们会删除您的二进制文件,因此您可以从头开始重建。

我怀疑当您重新运行“make”时,它会从您上次构建中获取旧的二进制文件。你检查它是否存在?

否则,我猜你的项目从一开始就不需要它 :)

运行“ld -M”来生成地图(应该包括交叉引用)是确认这一点的好方法。

于 2013-01-09T03:56:21.553 回答
0

链接器忽略了预期的错误,因为创建的行A.o由于#if.

#if (OBJ_A_SUPPORTED)

A* a = new A();

#endif

移动了 OBJ_A_SUPPORTED 定义的头文件。

这导致链接器从 A.cpp 中排除 fns,进而删除了对 fns in 的调用B.cpp。所以没有链接器错误。在我完全错过的这种情况下,仔细查看地图文件可能会产生一些线索。

于 2013-01-09T11:51:19.153 回答