ODR 违规(弱符号被弱符号覆盖)
有以下目录结构:
├── A
│ ├── A.cpp
│ ├── A.hpp
│ ├── A.o
│ └── Evil.hpp
├── B
│ ├── B.cpp
│ ├── B.hpp
│ ├── B.o
│ └── Evil.hpp
├── main.cpp
└── main.o
A.hpp:
#pragma once
#include "Evil.hpp"
struct A {
A();
~A();
Evil mid;
};
A.cpp:
#include "A.hpp"
A::A() {
printf("OuterClass A ctor\n");
}
A::~A() {
printf("OuterClass A dtor\n");
}
Evil.hpp: (from A/)
#pragma once
#include <cstdio>
struct Evil {
Evil() {
printf("Evil A ctor\n");
}
};
B.hpp:
#pragma once
#include "Evil.hpp"
struct B {
B();
~B();
Evil mid;
};
B.cpp:
#include "B.hpp"
B::B() {
printf("OuterClass B ctor\n");
}
B::~B() {
printf("OuterClass B dtor\n");
}
Evil.hpp:
#pragma once
#include <cstdio>
struct Evil {
Evil() {
printf("Evil B ctor\n");
}
};
main.cpp
#include "A/A.hpp"
int main(){
A a;
return 0;
}
使用命令编译时:
g++ -c A.cpp
g++ -c B.cpp
g++ -c main.cpp
g++ main.o A.o B.o -o out
输出为:
Evil A ctor
OuterClass A ctor
OuterClass A dtor
但是命令时链接的更改:
g++ main.o B.o A.o -o out
输出是(当 Evil.hpp 定义不同时可能会崩溃):
Evil B ctor
OuterClass A ctor
OuterClass A dtor
我知道链接顺序很重要,但为什么在这种情况下没有定义符号?据我了解,Evil.hpp 在 hpp 文件中完全定义,因此是“内联”的,并且定义存在于所有包含的 cpp 中。有趣的是 nm 在 Ao 和 Bo 中输出的两个符号都是弱符号:
0000000000000000 W _ZN4EvilC1Ev
0000000000000000 W _ZN4EvilC2Ev
0000000000000000 n _ZN4EvilC5Ev
所以我认为这里的问题是:为什么来自 Ao 的弱符号会被来自 Bo 的其他弱符号覆盖?我认为弱符号只能被强符号覆盖? 编译于:
g++(Ubuntu 10.3.0-1ubuntu1)10.3.0
There is following directory structure:
├── A
│ ├── A.cpp
│ ├── A.hpp
│ ├── A.o
│ └── Evil.hpp
├── B
│ ├── B.cpp
│ ├── B.hpp
│ ├── B.o
│ └── Evil.hpp
├── main.cpp
└── main.o
A.hpp:
#pragma once
#include "Evil.hpp"
struct A {
A();
~A();
Evil mid;
};
A.cpp:
#include "A.hpp"
A::A() {
printf("OuterClass A ctor\n");
}
A::~A() {
printf("OuterClass A dtor\n");
}
Evil.hpp: (from A/)
#pragma once
#include <cstdio>
struct Evil {
Evil() {
printf("Evil A ctor\n");
}
};
B.hpp:
#pragma once
#include "Evil.hpp"
struct B {
B();
~B();
Evil mid;
};
B.cpp:
#include "B.hpp"
B::B() {
printf("OuterClass B ctor\n");
}
B::~B() {
printf("OuterClass B dtor\n");
}
Evil.hpp:
#pragma once
#include <cstdio>
struct Evil {
Evil() {
printf("Evil B ctor\n");
}
};
main.cpp
#include "A/A.hpp"
int main(){
A a;
return 0;
}
When compiled with commands:
g++ -c A.cpp
g++ -c B.cpp
g++ -c main.cpp
g++ main.o A.o B.o -o out
The output is:
Evil A ctor
OuterClass A ctor
OuterClass A dtor
But when order of linking is changed:
g++ main.o B.o A.o -o out
The output is (and possible crash when Evil.hpp definition is different):
Evil B ctor
OuterClass A ctor
OuterClass A dtor
I know that linking order matters but why in that case symbols are not defined? As I understand Evil.hpp is fully defined in hpp file hence is 'inlined' and definitions are present in all included cpp. The interesting part is that nm outputs in both A.o and B.o both symbols as weak:
0000000000000000 W _ZN4EvilC1Ev
0000000000000000 W _ZN4EvilC2Ev
0000000000000000 n _ZN4EvilC5Ev
So the question here I believe is: why weak symbol from A.o is overriden by other weak symbol from B.o? I thought that weak symbol can be overridden only by strong symbol?
Compiled on:
g++ (Ubuntu 10.3.0-1ubuntu1) 10.3.0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论