首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >未调用C++ / GCC -文件作用域对象的构造函数

未调用C++ / GCC -文件作用域对象的构造函数
EN

Stack Overflow用户
提问于 2015-09-27 20:36:21
回答 1查看 357关注 0票数 1

我开始为瑞萨RZ/A1L微控制器开发。瑞萨提供了一个集成开发环境(Eclipse Eclipse的修改版本),设置为与GCC一起编译C/ C++。一切都很好,但是...

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

代码语言:javascript
运行
复制
class NewClass {
public:
    int i;
    NewClass() {
        i = 4;
    }
};


NewClass newInstance;

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

我可以断定构造函数没有被调用,因为使用Renesas提供的在线调试设置,我可以看到我从来没有被设置为4(即使我进一步引用了newInstance和i;我也关闭了优化)。抱歉,我不能简单地计算出i的值--代码是在微控制器中运行的,而我还没有弄清楚怎么做。

如果我将NewClass newInstance;行放在main()中,那么问题就解决了。

这个问题的另一个后果是,为了继承类,在一个类上调用虚函数(通过基类类型的指针)会导致崩溃-我怀疑是因为构造函数没有执行,因此没有向内存中写入对象是什么类的指示器。

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

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

非常感谢你的帮助。

EN

回答 1

Stack Overflow用户

发布于 2015-09-27 20:53:36

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

basic.start.main/1程序应包含一个名为main的全局函数,它是程序的指定开始位置。独立环境中的程序是否需要定义main函数是由实现定义的。注意:在独立环境中,启动和终止是由实现定义的;启动包含命名空间范围内具有静态存储持续时间的对象的构造函数的执行;终止包含具有静态存储持续时间的对象的析构函数的执行。-结束注释

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

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

代码语言:javascript
运行
复制
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中,它看起来像这样:

代码语言:javascript
运行
复制
CRTBEGIN_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
CRTEND_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)

现在来看实际的初始化函数。在与内核入口点相同的文件中,先调用_init,然后再调用kernel_main (或其他任何名称)。也可以在kernel_main之后调用_fini,但这不太可能是必需的。确切的代码取决于体系结构,但这里有一个32位x86的示例:

代码语言:javascript
运行
复制
/* 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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32807964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档