Странное поведение при связывании, последняя версия G ++ - PullRequest
1 голос
/ 15 апреля 2011

Я столкнулся со странным поведением при связывании с g ++, однако я всего лишь студент, и мне было интересно, было ли это нормально.

Я пытаюсь связать ассемблерный код (машина: fedora 14gnome 32bits x86 i686 intel i7) с кодом c ++ и для того, чтобы ассемблерный код вызывал метод из функции, созданной в файле c ++.Кажется, что реализация метода в объявлении класса не позволит поместить его в таблицу компоновщика, если только он не используется хотя бы один раз в исходном источнике.

class A
{
public:
    void showSUP() {
        cout<<"sup";
    }
};

После создания экземпляра A вы не будетев состоянии вызвать _ZN1A7showSUPEv, потому что он не был помещен в таблицу ссылок:

call _ZN1A7showSUPEv

Однако, если вы вызываете A :: showSUP () в том же .cpp, как было объявлено A, товызов из отдельного файла сборки будет работать.

С (и создание экземпляра A)

class A
{
    void showSUP();
};

A::showSUP()
{
    cout<<"sup";
}

вызов _ZN1A7showSUPEv будет работать.

Мой вопроспочему не работает первый пример.

Спасибо всем заранее.

Ответы [ 3 ]

5 голосов
/ 15 апреля 2011

Существуют атрибуты, которые вы можете указать для функции следующим образом

classe A
{
  public:
    void showSUP(){
      cout<<"sup";
    } __attribute__((used))
};

см. Обзор атрибутов gcc

используется Найдено в версиях:3.1-3.4 Описание:

     This attribute, attached to a function, means that code must be
     emitted for the function even if it appears that the function is
     not referenced.  This is useful, for example, when the function

указывается только при сборке inline.

2 голосов
/ 15 апреля 2011

В общем, если вы хотите, чтобы функция была включена в конечную библиотеку / исполняемый файл, она должна быть:

  • используется
  • без встраиваемой

И inlined функция - это функция, код которой просто копируется и вставляется в том месте, где функция используется (компилятором), чтобы не было вызова функции. Это оптимизация возможностей, поэтому функция может быть встроенной в некоторых местах и ​​не встроенной в других, в зависимости от контекста. Большинство очень коротких функций (так называемые однострочные) обычно встроены.

В древние времена, чтобы быть встроенным, в текущей единице перевода необходимо было определить функцию, то есть:

  • либо он определен в заголовке (как в вашем случае), и, следовательно, может быть встроен во все источники, включая этот заголовок
  • либо он определен в исходном файле, и, следовательно, может быть встроен в этот исходный файл

В настоящее время у нас также есть LTO (Link Time Optimization), и, если он активирован, компоновщик может фактически вызывать вызовы функций. Эти оптимизации также ответственны за очистку результирующей библиотеки / двоичного файла от неиспользованных символов.

Существует два возможных решения вашей проблемы:

  • вместо этого определите функцию в исходном файле, она стандартна и не может быть уничтожена
  • использовать специальные атрибуты компилятора, чтобы пометить функцию как использованную, чтобы она не была уничтожена

В последнем случае, если вы хотите переносимости, я могу только посоветовать использовать макрос (ATTRIBUTE_USED) и определить его содержимое в зависимости от текущего используемого компилятора.

2 голосов
/ 15 апреля 2011
  • Для встроенных функций компилятор будет выводить код только там, где используется функция.
  • Функции определены внутри определения класса встроенный (обычно).
  • Функция не б.
  • Следовательно: в двоичный файл.
...