我正在使用为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?
答案 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