如何阻止g ++链接不需要的异常处理代码?

时间:2009-06-15 20:39:06

标签: c++ exception gcc g++

我正在使用为arm-eabi编译的GCC / G ++开发嵌入式应用程序。由于资源限制,我试图禁用标准C ++异常处理。我正在使用“-fno-exceptions”编译代码 -nostartfiles -ffreestanding“。

当一个类的全局实例存在,并且该类包含另一个类的实例作为成员时,则链接了许多异常处理代码。这不会那么糟糕,除了它还带来很多stdio的东西,比如printf,fopen,fclose和其他FILE函数。这个应用程序没有文件系统,即使这样做,这些函数也会浪费太多的代码空间。

我理解即使使用-fno-exceptions,G ++链接在使用异常的operator new中,因为库没有非异常使用的operator new(new(nothrow)除外)。我为operator new和delete创建了替换,这些替换链接到输出以及不需要的标准库函数。

让我感到困惑的是,我不会在任何地方打电话给新人。只有当一个全局对象包含另一个对象时才会链接所有这些代码。

例如:

class UartA {
...
private:
  Ringbuffer* rxbuf;
};

class UartB {
...
private:
  Ringbuffer rxbuf;
};

如果创建了UartA的全局实例,则不会链接异常处理,operator new和stdio内容。这就是我想要的。

如果创建了UartB的全局实例(其中rxbuf是实例而不是指针),则会链接不需要的代码。

UartA和UartB都不使用operator new,exception或stdio。它们的区别仅在于rxbuf的类型。

您能否建议如何防止链接额外的代码?另外,为什么这与UartB相关联,而不是UartA?

3 个答案:

答案 0 :(得分:5)

我认为最接近的是编译链接-fno-exceptions和-fno-rtti。如果有更好的方法摆脱其余的,我会很高兴自己听到它。

至于摆脱新的,请尝试-nostdlib。

答案 1 :(得分:5)

因为你基本上是在做OS开发人员为了获得一个独立的c或c ++环境所做的事情。您可能希望仅使用自定义链接描述文件。你需要小心,因为像全局构造函数这样的东西不再自动发生。但是你也没有得到任何你没有明确要求的东西(并且编写代码来调用全局构造函数并不困难)。这是我操作系统的链接描述文件。

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)

virt = 0xc0100000; /* 3.1 gig */
phys = 0x00100000; /* 1 meg */

SECTIONS
{ 
    .text virt : AT(phys) 
    {
        code = .; _code = .; __code = .;
        *(.text)
        *(.gnu.linkonce.t*)
        . = ALIGN(4096); 
    }

    .rodata : AT(phys + (rodata - code))
    {
        rodata = .; _rodata = .; __rodata = .;
        *(.rodata*)
        *(.gnu.linkonce.r*)
        __CTOR_LIST__ = .;
        LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) 
        *(.ctors) 
        LONG(0) 
        __CTOR_END__ = .; 

        __DTOR_LIST__ = .; 
        LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) 
        *(.dtors) 
        LONG(0) 
        __DTOR_END__ = .; 
        . = ALIGN(4096); 
    }

    .data : AT(phys + (data - code))
    {
        data = .; _data = .; __data = .;    
        *(.data)
        *(.gnu.linkonce.d*)
        . = ALIGN(4096); 
    }

    .tbss : AT(phys + (tbss - code)) 
    {
        tbss = .; _tbss = .; __tbss = .;
        *(.tbss)
        *(.tbss.*)
        . = ALIGN(4096); 
    }

    .bss : AT(phys + (bss - code)) 
    {
        bss = .; _bss = .; __bss = .;
        *(.bss)
        *(.bss.*)
        *(COMMON)
        *(.gnu.linkonce.b*)
        . = ALIGN(4096); 
    }

    end = .; _end = .; __end = .;
}

它可能比您需要的更多(将部分对齐到4k边界,所有符号都在> 3GB标记处)但是是一个很好的起点。

你可以像这样使用它:

ld -T link_script.ld *.o -lc -o appname

“-lc”也应该在libc中链接,如果那就是你想要的。

答案 2 :(得分:0)

您可以尝试捕获新内容以查看它是否真的被调用。

在某些情况下可能会隐式发生新情况,例如复制构造。

您可以通过略微区别地编写代码来删除它们。

http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter11_013.html