【问题标题】:Why does the function name in .o file different from the one in .cc file after compiling?为什么 .o 文件中的函数名和 .cc 文件中编译后的函数名不同?
【发布时间】:2013-08-14 22:46:50
【问题描述】:

我使用以下命令编译了一个 .cc 文件,该命令位于 Makefile 代码中:

bin/bash ../libtool --silent --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I.
-I.. -I../include/ -I..    -g -O2 -MT rtpsession_inet.lo -MD -MP -MF 
.deps/rtpsession_inet.Tpo -c -o rtpsession_inet.lo rtpsession_inet.cc

.cc 文件中有一个名为 rtp_session_rtp_recv 的函数。但是据说使用Makefile生成的库时找不到这个函数的引用。

于是我查看了rtpsession_inet.cc生成的.o文件,发现并没有一个名为rtp_session_rtp_recv的函数,而函数名改为_Z20rtp_session_rtp_recvP11_RtpSessionj。 p>

同时,还有其他几个函数更改了它们的名称,例如rtp_session_rtp_send -> _Z20rtp_session_rtp_sendP11_RtpSessionP4msgb

但是rtp_session_set_remote_addr_full等函数根本没有改变。

附加字符的含义是什么?我该如何处理这个问题?

我在Linux中编译文件并使用命令

nm rtpsession_inet.o

读取 .o 文件。 (包括名字不正确的所有函数都带有T标签,表示存在引用)

谢谢!

【问题讨论】:

标签: linux function compiler-construction makefile g++


【解决方案1】:

这叫name mangling

这是为了链接器的利益。 C++ 编译器能够根据参数类型解析多个同名函数。例如,您可能有一个名为print 的函数接受int 参数,另一个接受char* 参数。编译器会根据您传递给它的参数类型知道要生成调用哪个。

但是,跨翻译单元的调用必须由链接器解析,链接器通常不知道 C++ 重载规则,只能根据名称解析调用。因此,C++ 编译器使用足够的信息来修饰名称以解决重载问题。

C++ 标准没有具体说明这是如何完成的,但是如果您查看名称,您可能会知道错误名称是如何生成的。

我该如何处理这个问题?

编译器和链接器应该正确解析调用。你指的是什么问题?

【讨论】:

  • 我在一个项目中遇到了这个问题,项目的最终结果是一个库(.so)文件。当尝试使用这个库编译另一个示例程序时,据说:/usr/local/lib//libortp.so: undefined reference to rtp_session_rtp_recv。不知道为什么找不到引用,怀疑是函数名不同造成的。顺便说一句,我用来编译示例程序的命令是g++ -L /usr/local/lib/ -I /usr/local/include/ortp/ -I /usr/include/ rtpsend.c -o rtpsend -lortp
  • @zzy 看看 'extern "C"{}' 以避免破坏直接的 C 调用。
  • 当我将extern "C" 添加到int rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts)', it is said that 'rtpsession_priv.h:49:5: error: previous declaration of 'int rtp_session_rtp_recv(RtpSession*, uint32_t)' with 'C++' linkage 的头部时。并且在将extern "C"也添加到头文件之后,就说rtpsession_priv.h:49:8: error: expected identifier or '(' before string constant。那么如何使用呢?
  • extern "C" 仅在 C++ 代码中有效。如果您需要它在 C 和 C++ 源文件的标头中为 #included,则需要将其包含在 #include __cplusplus 中。有关混合 C 和 C++ 代码的信息,请参阅 C++ FAQ 中的 this section
  • @zzy:你是否在同一个程序中混合了 C 和 C++ 代码?如果是这样,您应该在您的问题中提到这一点,而不是假设名称修改是问题并只是询问这个问题。 meta.stackexchange.com/questions/66377/what-is-the-xy-problem
【解决方案2】:

附加字符是编译器添加的符号“装饰”,用于标识函数/方法签名,即返回类型和参数。它帮助运行时确定在任何给定的调用中调用多个同名(重载)函数中的哪一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多