C ++ / GCC - 未调用文件范围对象的构造函数

时间:2015-09-27 12:36:21

标签: c++ gcc constructor initialization

我开始为瑞萨RZ / A1L微控制器开发。瑞萨提供IDE(e2 Studio - Eclipse的修改版本),设置为使用GCC编译C / C ++。一切正常,但......

如果我在文件范围内声明一个对象(在任何函数之外),则永远不会调用它的构造函数。例如:

class NewClass {
public:
    int i;
    NewClass() {
        i = 4;
    }
};


NewClass newInstance;

int main(void)
{
    // My program...
}

我可以告诉构造函数没有被调用,因为使用瑞萨提供的在线调试设置,我可以看到我从未设置为4(即使我对newInstance和i进行了进一步的引用;我优化已关闭)。对不起,我不能做一个简单的cout我的价值 - 代码是在微控制器中运行的,我还没有想出如何做到这一点。

如果我改为将NewClass newInstance;行放在main()中,那么问题就会消失。

问题的另一个后果是,对于继承类,在一个上调用虚函数(通过基类类型的指针)会导致崩溃 - 我怀疑由于构造函数没有执行而因此没有写入记忆对象是什么类的一些指标。

通常会通过什么机制调用这样的构造函数?我做了一些谷歌搜索 - 它会是“.ctors”列表吗? (https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

瑞萨的“模板”C ++项目确实包含调用所有ctors的代码;但是,通过查看我为项目生成的.map文件,我可以看到实际上没有ctors存在。这是否缩小了问题的范围 - GCC编译器是不应该将它们吐出来的?

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:3)

引用C ++ 11标准草案N3337,我们发现:

  

[basic.start.main] / 1程序应包含一个名为的全局函数   main,这是该计划的指定开始。它是   实现 - 定义一个独立环境中的程序   需要定义main函数。 [注意:独立式   环境,启动和终止是实现定义的;   start-up包含对象的构造函数的执行   名称空间范围,具有静态存储持终止包含   为具有静态存储持续时间的对象执行析构函数。 -   结束记录]

正如您所看到的,它是在独立环境中定义的实现。因此,假设您有一个32位x86 GCC工具链......

听起来你处于一个独立的环境中。如果是这样,如果要使用全局构造函数,则需要实现一些样板。您链接的初始化页面提到了一个链接器行,如下所示:

i686-elf-ld crt0.o crti.o crtbegin.o foo.o bar.o crtend.o crtn.o

假设foo.obar.o是您的计划的一部分,必需您的链接器行看起来像这样。请注意,编译器应提供自己的crtbegin.ocrtend.o,以便您可以找到使用-print-file-name的位置。在Makefile中,它看起来像这样:

CRTBEGIN_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
CRTEND_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)

现在进行实际的初始化功能。在与内核入口点相同的文件中,在_init之前调用kernel_main(或者调用它的任何内容。)可以在_fini之后调用kernel_main,但不一定需要/* x86 crti.s */ .section .init .global _init .type _init, @function _init: push %ebp movl %esp, %ebp /* gcc will nicely put the contents of crtbegin.o's .init section here. */ .section .fini .global _fini .type _fini, @function _fini: push %ebp movl %esp, %ebp /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ /* x86 crtn.s */ .section .init /* gcc will nicely put the contents of crtend.o's .init section here. */ popl %ebp ret .section .fini /* gcc will nicely put the contents of crtend.o's .fini section here. */ popl %ebp ret 。确切的代码将取决于体系结构,但这是32位x86的示例:

has_and_belongs_to_many :requests