Как я могу остановить g ++ от связывания нежелательного кода обработки исключений? - PullRequest
5 голосов
/ 16 июня 2009

Я разрабатываю встраиваемое приложение с использованием GCC / G ++, скомпилированного для arm-eabi. Из-за нехватки ресурсов я пытаюсь отключить стандартную обработку исключений C ++. Я компилирую код с "-fno-excptions -nostartfiles -ffreestanding ".

Когда существует глобальный экземпляр класса, и этот класс содержит экземпляр другого класса в качестве члена, тогда связывается много кода обработки исключений. Это не было бы так плохо, за исключением того, что оно также приносит во многих вещах stdio, таких как printf, fopen, fclose и другие функции FILE. Это приложение не имеет файловой системы, и даже если это так, эти функции тратят слишком много места на коде.

Я понимаю, что даже при использовании -fno-exceptiontions G ++ связывается в операторе new, который использует исключения, поскольку в библиотеке нет оператора new, не использующего исключения (кроме new (nothrow)). Я создал замены для операторов new и delete, и они связаны с выводом, а также с нежелательными функциями стандартной библиотеки.

Что меня удивляет, так это то, что я нигде не звоню. Весь этот код связан только тогда, когда глобальный объект содержит другой объект.

Например:

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

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

Если создан глобальный экземпляр UartA, обработка исключений, операторы new и материал stdio не связаны между собой. Это то, что я хочу.

Если создается глобальный экземпляр UartB (где rxbuf - это экземпляр, а не указатель), нежелательный код связывается.

Ни UartA, ни UartB не используют оператор new, исключения или stdio. Они отличаются только типом rxbuf. * ​​1016 *

Можете ли вы подсказать, как предотвратить добавление дополнительного кода? Кроме того, почему это связано для UartB, но не для UartA?

Ответы [ 3 ]

5 голосов
/ 16 июня 2009

, поскольку вы в основном делаете то, что разработчик ОС делал бы, чтобы получить автономную среду 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 = .;
}

Вероятно, он делает больше, чем нужно (выравнивает разделы по границам 4 КБ, содержит все символы с отметкой> 3 ГБ), но является хорошей отправной точкой.

Вы можете использовать его так:

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

"-lc" также должен ссылаться в libc, если вы этого хотите.

5 голосов
/ 16 июня 2009

Я думаю, что самое близкое, что вы можете получить, это компилировать и , связывающие с -fno-exceptions и -fno-rtti. Если есть лучший способ избавиться от всего остального, я был бы рад услышать это сам.

Чтобы избавиться от нового, попробуйте -nostdlib.

0 голосов
/ 16 июня 2009

Вы можете попробовать перехватить новое, чтобы узнать, действительно ли оно вызывается.

Новое может возникать неявно при некоторых обстоятельствах, например при копировании.

Вы можете удалить их, написав код немного по-другому.

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

...