C++ ctor 问题 (linux)
环境:linux,通过 g++ 从几个 C++ 文件创建的用户空间应用程序 (结果是一个 ELF)
-
遍历构造函数列表时出现问题(SIGSEGV)
( __CTOR_LIST__ )
(注意:通过此列表调用的代码是一种系统每个类的初始化, 不是我编写的构造函数代码)
- 当我正确理解每个编译单元(从 .cpp 创建的每个 .o)时 创建一个条目
__CTOR_LIST__
当我通过程序单步执行 GDB 时,
用于调试此 I正在寻找一种在之前添加自己的代码的方法 调用
"_do_global_ctors_aux"
对此有何提示
谢谢,
乌韦
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
造成这种情况的可能原因有很多。 从您访问尚未创建的对象开始(因为跨不同翻译单元的对象创建顺序未定义),我认为在这种情况下很有可能,并且范围到您的构建环境上的错误。
要使自己的函数在其他构造函数之前被调用,您需要定义一个构造函数(优先级)属性此处。 GCC 为每个文件的构造函数输入部分保留优先级。 它按照这些优先级的顺序将它们联系起来。 在我的 Linux 系统的链接描述文件中,该代码如下所示(使用 ld -verbose 输出它):
您需要给它一个低优先级,以使其在其他具有更高的优先级编号。 但从表面上看,没有编号的构造函数似乎会先执行。 完全不确定。 最好你尝试一下。 如果您希望在 _do_global_ctors_aux 之前调用您的函数,则必须释放通常在 ELF 加载程序加载程序时执行的原始
_init
函数(查看-init< /code> ld 的选项)。 自从我搞乱它以来已经有一段时间了,但我记得它必须做一些初始化的亲密细节,所以我不会尝试替换它。 尝试使用我链接到的构造函数属性。 但是,请务必小心。 您的代码可能会在构造其他重要对象(例如
cout
)之前执行。更新:我做了一个测试,它实际上反向执行了ctor函数。 首先链接的 Soctor 函数稍后执行。 这段代码恰好位于 gcc 源代码的 crtstuff.c 中:
我做了一个小测试:
与
--print-map
链接会产生以下输出:注意
.ctors .65535
是我们通过属性优先级0
隐式创建的部分。 现在,如果你给予它优先级,gcc 会发出警告,这是完全正确的:p我通过中断
doit
和dothat
来测试它,并按顺序调用它们我们期待。 玩得开心!There are many possible reasons of this. Ranges from that you access objects not yet created (because order of creation of objects across different translation units is undefined) which i think is quite probable in this case, and ranges to an error on your build-environment.
To make a own function be called before other constructor function, you have a
constructor (priority)
attribute described here. GCC keeps a priority for each files' constructor input section. And it links them in order of those priorities. In the linker script of my linux system, that code looks like this (output it usingld -verbose
):You would want to give it a low priority to make it execute before other registered ctor functions having a higher priority number. However from the looks of it, it seems like constructors having no number will be executed first. Not sure entirely. Best you give it a try. If you want to have your function called even before _do_global_ctors_aux, you have to release the original
_init
function that is normally executed when your program is loaded by the ELF loader (look into the-init
option of ld). It's been some time since i messed with it, but i remember it has to do some intimate details of initialization, so i wouldn't try to replace it. Try using the constructor attribute i linked to. However, be very careful. Your code will possibly be executed before other important objects likecout
are constructed.Update: I did a test, and it actually executes ctor functions in reverse. So ctor functions that are linked first are executed later. This code happens to be in crtstuff.c of the gcc source code:
I made a little test:
Linking with
--print-map
yields, among others, this output:Notice how
.ctors.65535
is the section we implicitly created by our attribute priority0
. Now, if you give it that priority, gcc warns and it's totally right :pI tested it by breaking on
doit
anddothat
, and it called them in the order we expect. Have fun!不是您问的问题,但是...
在 C++/g++ 中,您可以拥有一个类,其中声明的 [header] 方法永远不会在源 [.cc] 文件中实际定义,只要这些方法从未被调用。
因此,您可以将当前的代码文件复制到临时目录,对它们进行修改,运行[手动]二分搜索,并相当快速地隔离问题。
不优雅,但非常有效。
除了臭名昭著的“静态初始化顺序”问题之外,还有更多深奥的案例,例如最近在 Charles Bailey 的SO(请参阅评论)。
将产生类似的核心转储问题。
Not the question you asked, but...
In C++/g++, you can have a class where the declared [header] methods are never actually defined in the source [.cc] files as long as those methods are never invoked.
As a consequence, you can copy your current code files to a temporary directory, do a hack and slash job on them, run a [manual] binary search, and isolate the problem fairly quickly.
Not elegant, but highly effective.
Aside from the infamous "Static Initialization Order" issue, there are also more esoteric cases such as the one recently pointed out to me here on SO by Charles Bailey (see the comments).
Will produce a similar coredump problem.
您可能被所谓的“静态初始化顺序惨败”所困扰。
基本上,当存在多个翻译单元(即 C++ 源文件)并且每个文件定义一个全局对象时,C++ 编译器/链接器不可能确定首先构造哪个。 如果
x
依赖于首先构造的y
,但编译/链接偶然导致x
在y
之前构造,程序通常会崩溃。 有关更多详细信息,请参阅 C++ FAQ Lite 的项目 [10.12]。 项目[10.13]包含一个解决方案——“首次使用时构建”习惯用法。It's possible that you're being bitten by the so-called "Static Initialization Order Fiasco".
Basically, when there is more than one translation unit (that is, C++ source file), and each file defines a global object, it is not possible for the C++ compiler/linker to establish which to construct first. If
x
depends ony
being constructed first, but by chance compilation/linking causesx
to be constructed beforey
, the program will typically crash. See item [10.12] of the C++ FAQ Lite for more details. Item [10.13] contains a solution -- the "construct on first use" idiom.