- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
原始问题分布在来自不同项目的数十万个 LoC 中。它包含很多成分:内联汇编、虚拟继承、间接级别、不同的编译器和编译器选项。 (这就像一部惊悚片。)我很难简化到这个 SSCCE:
// a.hpp
struct A {
int i;
~A() { asm("" : "=r"(i)); }
};
struct B : public virtual A { };
struct C : public B { };
struct D {
D(C);
};
// a.cpp
#include "a.hpp"
void f(C) {
}
D::D(C c) {
f(c);
}
// main.cpp
#include "a.hpp"
int main() {
C c;
D d(c);
}
使用这些命令行构建:
g++ -O3 -fPIC -c a.cpp
clang++ -O3 -fPIC -c main.cpp
clang++ -fuse-ld=gold main.o a.o -o main
链接器的输出是:
a.o:a.cpp:function D::D(C) [clone .cold]: error: relocation refers to global symbol "construction vtable for B-in-C", which is defined in a discarded section
section group signature: "_ZTV1C"
prevailing definition is from main.o
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
我相信 gcc、clang 或 gold 中存在错误。 我的问题是它在哪里?(我猜它是金子,但我想在报告错误之前确定一下。)
FWIW:正如我所说,所有成分都很重要,如果例如删除 asm
,问题就会消失。使问题消失的更显着的变化是:
-fuse-ld=gold
)main.cpp
,不带-O3
。-fPIC
编译main.cpp
。a.o
和 main.o
。最佳答案
这似乎是 GCC 中的一个错误,但是内联汇编在 ABI 之外,可以简单地使这成为 GCC 和 Clang 之间不幸的不兼容。
问题是内联汇编让 GCC 认为 ~A::A()
可以引发异常,因此它在 D::D()
中创建异常处理路径,这需要一个用于 B-in-C 的构造 vtable,它放置在还包含 C 的 vtable (_ZV1C
) 的 COMDAT 组。
因为 Clang 不会在 _ZV1C
COMDAT 组中生成构造 vtable,而 GCC 会生成,所以您最终会遇到这样一种情况,即链接器可能会保留 Clang 生成的 COMDAT 组,并丢弃 GCC - 具有构造 vtable 的生成版本。如果您链接到 GCC 生成的需要额外符号定义的代码,则会收到此错误。
在你的链接中反转 main.o 和 a.o 也可以解决这个问题,因为所有三个链接器都会让 COMDAT 组远离 a.o,这是第一个看到的。
这是 GCC 从 a.o 为 D::D() 生成的代码:
0000000000000002 <_ZN1DC1E1C>:
2: 48 83 ec 18 sub $0x18,%rsp
6: 48 8b 06 mov (%rsi),%rax
9: 48 8b 40 e8 mov -0x18(%rax),%rax
d: 8b 04 06 mov (%rsi,%rax,1),%eax
10: 89 44 24 08 mov %eax,0x8(%rsp)
14: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax
17: R_X86_64_REX_GOTPCRELX _ZTV1C-0x4
1b: 48 8d 40 18 lea 0x18(%rax),%rax
1f: 48 89 04 24 mov %rax,(%rsp)
23: 48 89 e7 mov %rsp,%rdi
26: e8 00 00 00 00 callq 2b <_ZN1DC1E1C+0x29>
27: R_X86_64_PLT32 _Z1f1C-0x4
2b: eb 17 jmp 44 <_ZN1DC1E1C+0x42>
2d: 48 89 c7 mov %rax,%rdi
30: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax
33: R_X86_64_PC32 _ZTC1C0_1B+0x14
37: 48 89 04 24 mov %rax,(%rsp)
3b: 89 44 24 08 mov %eax,0x8(%rsp)
3f: e8 00 00 00 00 callq 44
40: R_X86_64_PLT32 _Unwind_Resume-0x4
44: 48 83 c4 18 add $0x18,%rsp
48: c3 retq
从偏移量 0x2d 到 0x3f 处的 callq
的代码是异常的处理路径,在f(c)
调用过程中发生异常时生成。 0x30 处的 lea
指令引用了 B-in-C 的构造 vtable 中的一个条目 (_ZTC1C0_1B
)。
如果没有内联汇编,GCC 会生成与 clang 相同的代码,没有异常处理路径,也不需要构建 vtable。
用--no-exceptions
编译,问题也消失了。
无论是在 -O0
、-O1
、-O2
还是 -O3 编译 a.cpp,我都看到了同样的问题
。
至少GCC在编译a.cpp和main.cpp的时候是一致的,所以可以有人认为这种情况根本不包括在 C++ ABI 和 GCC 中Clang 可以自由地以不同的方式对待它。我做了一些微不足道的尝试用内联 asm 以外的东西重现,但不能。
至于为什么您从 gold 中收到错误,而不是从 bfd 或 lld 中收到错误,黄金报告可能是一个真正的错误,尽管在这个特殊情况,因为永远不会抛出异常,异常处理代码永远不会执行。但是当你链接bfd ld 或 lld,0x30 处的 lea
指令未重定位,没有警告,程序可能会崩溃调用 f()
时抛出异常。
关于c++ - 链接错误 : construction vtable defined in a discarded section,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64118757/
我在提交更改时不小心单击了放弃。所以我丢弃了整个文件,但我只想丢弃一些大块头。但是我没有点击提交,我没有点击取消。 但是现在我在我的文件中看不到我的代码。 我该怎么做才能撤消该死的丢弃? 提前致谢 最
我们有一个变更集,开发人员已在其中 checkin 了对源分支和目标分支的更改,许多更改包括两个分支中的重命名。从源分支到目标分支的变更集合并正常,但变更集仍保留在要合并的变更集列表中。 当我现在尝试
设置: 我有一个表单和一个“提交”按钮。理想情况下,用户应该填写表格,单击“提交”,然后离开选项卡。如果他尝试离开选项卡而不保存更改,我需要通过 3 个选项提醒他: 保存 放弃:放弃表单数据更改,并保
从 C# 7 开始,我们可以使用丢弃 _ 来丢弃未使用的变量。我用它做的事情之一是即发即弃任务。 考虑这个方法: public Task Example() { // Do some fire
昨晚不经意间做了一件很蠢的事。我已经在 iPad 项目上工作了几个月并且(甚至更愚蠢)没有备份。通过在 XCODE 中右键单击该项目,我错误地单击了“放弃更改” (愚蠢再次占据上风)自最初以来我没有任
我有一个修改和实例化的 Action ,然后链接到另一个 Action 。如果实例上有错误,我想忽略所做的更改。但是,throws()方法不起作用。状态更改始终保持不变。我究竟做错了什么? def r
我刚刚意识到 GL_ALPHA_TEST自 OpenGL 3.0 起已被弃用,因此我无法将它与 glEnable() 一起使用。我已经尝试快速搜索谷歌现在如何替换它(以及为什么它被弃用),但未能找到这
使用 CPP map ,从 eclipse 编辑器获取警告信息。 Point find_shortest_node(const vector &openset,const map &f_score
我不理解以下示例中 x3 的行为(取自更大的语法)。 当然,语法有点奇怪,但大致实现了 (lal)?()? .当第二组不存在时,默认为 .我不明白为什么要输入 "lal"我得到 defaultcha
这个问题在这里已经有了答案: Is there a way to make bash job control quiet? (5 个答案) 关闭 3 年前。 我正在运行这个命令: nohup goo
当我尝试在 LWJGL 3 中实现纹理的透明度时,模型似乎以完全透明的方式渲染,因此根本不可见。当我删除支票时,它工作正常。有什么线索可以解释为什么吗? 下面是检查 alpha 分量的着色器代码: #
使用 GCC 和 C99 模式,我有一个函数声明为: void func(float *X); 当我调用该函数时,我使用了一个可变数组 Y: volatile float Y[2]; int main
本文整理了Java中org.jruby.parser.YYDebug.discard()方法的一些代码示例,展示了YYDebug.discard()的具体用法。这些代码示例主要来源于Github/St
可以使用加号按钮“暂存此行”轻松暂存行。 有“Discard Hunk”和“Stage Hunk”符号。 但是如何“丢弃行”呢?有什么快捷方式可以将行旁边的加号按钮更改为减号按钮吗? 最佳答案 您可以
我已经使用 jQuery.ajax() 方法构建了实时搜索。在每个 keyup 事件中,它都会从服务器接收新的结果数据。 问题是,当我打字速度非常快时,例如“foobar”和“fooba”的GET请求
我有一个看起来像这样的图形日志: (snip) | | | o 1) Other Dev: Commit | | \ o | | 2) Me: Commit / | | | |
我只是想将 mesos 版本从 1.0.3 升级到 1.3.1。 Chronos 调度程序能够通过 mesos 调度 JOB。该作业运行良好并且能够看到 mesos stdout 日志。但是,仍然在
我有一个要调试的 BufferedInputStream。为此,我使用此方法(Log.d 和 Log.wtf 只是 Android 特定的日志记录工具,除此之外其行为不应与纯 Java 不同):
假设它是使用“放弃 merge 中的所有更改...”选项执行 merge 的,但意外。 这个错误的提交已经提交到“中央”存储库中。 如果我遇到这种情况如何处理需要以正确的方式 merge 分支的变化?
我尝试将数据从 Firebase 数据库检索到我的回收站 View ,无论我尝试什么,我都会收到此错误。我该如何解决这个问题? 在我的模拟器中,Google Play 服务版本是:11.5.80 我没
我是一名优秀的程序员,十分优秀!