C++ ctor问题(linux)

1 c++ linux constructor elf segmentation-fault

  • 环境:linux,用户空间应用程序通过g ++从几个C++文件创建(结果是ELF)

  • 遍历构造函数列表时出现问题(SIGSEGV)

    ( __CTOR_LIST__ )

(注意:通过此列表调用的代码是每个类的一种系统初始化, 而不是我编写的构造函数代码)

  • 当我正确理解每个编译单元(每个.o创建一个.cpp)创建一个条目
    __CTOR_LIST__ 
  • 当我通过程序通过GDB步进时,问题(SIGSEGV)不存在

  • 为了调试这个我正在寻找一种方法来在调用之前添加自己的代码

    "_do_global_ctors_aux"

有什么提示吗?

谢谢,

乌韦

Joh*_*itb 7

这有很多可能的原因.你访问尚未创建的对象的范围(因为不同的翻译单元创建对象的顺序是未定义的),我认为在这种情况下很可能,并且在构建环境中存在错误.

要在其他构造函数之前调用自己的函数,您可以在此处constructor (priority)描述属性.GCC为每个文件的构造函数输入节保留优先级.它按照这些优先顺序将它们联系起来.在我的linux系统的链接器脚本中,该代码看起来像这样(使用它输出):ld -verbose

  .ctors          :
  {
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
Run Code Online (Sandbox Code Playgroud)

您可能希望给它一个低优先级,使其在具有更高优先级编号的其他已注册的ctor函数之前执行.然而从它的外观来看,似乎首先执行没有数字的构造函数.不完全确定.最好你试一试.如果你想在_do_global_ctors_aux之前调用你的函数,你必须释放_init当你的程序由ELF加载器加载时通常执行的原始函数(查看-initld 的选项).自从我搞砸了它已经有一段时间了,但我记得它必须做一些初始化的细节,所以我不会尝试替换它.尝试使用我链接到的构造函数属性.但是,要非常小心.您的代码可能会在cout构建其他重要对象之前执行.

更新:我做了一个测试,它实际上反过来执行ctor功能.因此,首先链接的ctor函数将在稍后执行.此代码恰好位于gcc源代码的crtstuff.c中:

  func_ptr *p;
  for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
    (*p) ();
Run Code Online (Sandbox Code Playgroud)

我做了一点测试:

void dothat() { }
struct f {
    f() { dothat(); }
} f_;
void doit() __attribute__((constructor (0)));
void doit() { }
int main() { }
Run Code Online (Sandbox Code Playgroud)

--print-map产量与产量联系起来:

.ctors          0x080494f4       0x10
 *crtbegin.o(.ctors)                 
 .ctors         0x080494f4        0x4 /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/crtbegin.o
 *crtbegin?.o(.ctors)                                                                
 *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)                                        
 .ctors         0x080494f8        0x4 /tmp/ccyzWBjs.o                                
 *(SORT(.ctors.*))                                                                   
 .ctors.65535   0x080494fc        0x4 /tmp/ccyzWBjs.o                                
 *(.ctors)                                                                           
 .ctors         0x08049500        0x4 /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/crtend.o  
Run Code Online (Sandbox Code Playgroud)

请注意.ctors.65535我们的属性优先级是如何隐式创建的部分0.现在,如果你给予它优先权,gcc警告并且完全正确:p

test.cpp:7:警告:从0到100的构造函数优先级保留给实现

我打破上测试它doitdothat和它在我们预计的顺序叫他们.玩得开心!