我有两个类,它们在自己的标头中独立声明,并在自己的 TU /.cpp 中定义了方法。
这些类在名称和命名空间方面是相同的,但存在于代码库中的不同目录中,并且具有不同的功能,它们如下所示:
core1/abc1.h:
namespace ns {
class abc {
....
std::map<std::string,int> m;
};
}
core1/abc1.cpp:
namespace ns {
abc:~abc() {
};
}
core2/abc2.h:
namespace ns {
class abc {
std::unordered_map<std::string,int> m;
};
}
core1/abc2.cpp:
namespace ns {
abc:~abc() {
};
}
当我运行使用这两个类的程序时,当程序结束并且调用析构函数时,它似乎基于来自 abc2.h 类型的实例的 gdb,即 abc1 的析构函数.h 类型正在被调用,这会导致段错误。
我在使用 g++ 和 clang 时看到错误,这可能是一个“未定义行为”问题吗?或者潜在的链接器错误? (链接器是金色的)
在构建与链接器一起使用的符号名称时,是否考虑文件名 - 或者仅考虑命名空间、类、方法名称?
文件名对链接没有影响,只影响全id。标准规定,禁止具有本地链接的项目,有两个定义 变量、函数、类类型、枚举类型或模板是未定义的行为。
通常,链接器可以检测到冲突,但由于对原始代码进行了转换,可以避免冲突,例如内联或完整程序优化。在链接级别,不再保留类的结构,仅保留函数代码和 vtable(如果存在)。 如果函数调用是完全内联的,则其名称可能不会出现在生成的目标代码文件中包含的符号表中。假设只有一个析构函数,完整的程序优化实际上可以做任何事情。
在这种情况下,如果每个版本的类都只有内联成员,并且此类实例从未在另一个模块中使用,那么您可能永远不会遇到错误,并且您可能会遇到非常奇怪的错误,有时只能通过查看来找到其本质转化为汇编代码。没有名称冲突 - 链接器没有错误。
运行调试器可能会导致您无法链接调试信息或显示执行的错误代码。认为自己很幸运。类似的错误在 vtable 中有所不同,一个类比另一个类具有更多的虚拟函数,我必须通过比较在我未知的架构的汇编程序中调用代码所使用的偏移量来诊断。