我不是任何语言或GCC的专家。所以我的问题可能低于标准。
我正在使用GCC构建包含数千个CPP文件的代码库。在一个文件中说A.cpp
我在B.cpp
中调用了一些函数[B.cpp
包含了定义为B.h
的类的类方法定义]。构建很好。但后来我从makefile中排除了B.o
。所以现在没有创建对象文件B.o
。但是在这种情况下,由于A.cpp
引用B.cpp
中的函数,我在编译或链接阶段时会遇到错误。但是没有,代码仍然没有错误地构建。但当我将fn调用从A.cpp
移动到另一个文件C.cpp
时,它给了我一个链接器错误,这是我认为的预期行为。
这是预期的行为吗?我还检查了在构建期间创建的映射文件,其中列出了所有函数名称,即使未创建B.cpp的目标文件,映射中也存在B.cpp
中的函数。所以我的问题是,当我从一个不属于构建的文件中调用函数时,为什么没有错误。我尝试删除以前版本中的所有目标文件和二进制文件,以清除可能存在的任何残留物,但无济于事。我没有线索。有人可以提供一些帮助吗?
在我的地图文件中,正常功能列为
80010820 T __gccmain
80010828 t __gccmain_end
等
但是B.cpp的fns列为
U CNvThread::ProcMsgReq(unsigned, void*)
U CNvDbMgrThread::Singleton(unsigned long)
答案 0 :(得分:1)
如果B.o
仍然存在于上一个版本中,它将与旧版本链接正常(除非某些重大更改)。如果你没有构建最终的可执行文件,并且只构建了A.o
,那么这仍然没有问题,因为A.o
引用了B
中的函数,但是直到最后才与它们链接输出文件链接。
同样,如果B.o
仍然存在于上一个版本中,则会使用它,这就是它出现在地图文件中的原因。
答案 1 :(得分:1)
听起来你有一个“makefile”:好。
默认情况下,“make”会(通常)尝试构建您的项目。无论如何,这是标准惯例。
通常,make也会有其他“目标”。例如,您可以键入“make clean”或“make cleanall”。如果存在这些目标,他们将删除您的二进制文件,因此您可以从头开始重建。
我怀疑当你重新运行“make”时,它会从你上一次构建中获取旧的二进制文件。你检查一下它是否存在?
否则,我猜你的项目从来没有真正需要它:)
运行“ld -M”生成地图(应该包含交叉引用)是确认这一点的好方法。
答案 2 :(得分:0)
链接器忽略了预期的错误,因为由于A.o
而未编译创建#if
的行。
#if (OBJ_A_SUPPORTED)
A* a = new A();
#endif
移动了OBJ_A_SUPPORTED定义的头文件。
这导致链接器从A.cpp中排除fns,然后在B.cpp
中删除对fns的调用。所以没有链接器错误。好好看看地图文件可能会在这种情况下产生一些线索,我完全错过了。