Смешивание отдельно скомпилированных объектов - PullRequest
4 голосов
/ 31 октября 2019

Давайте у меня будет класс class Drawable. Он может иметь много членов, функций-членов, родительских классов или может быть очень простым. Ради этого примера это не важно. Также предположим, что это какой-то элемент GUI.

Тогда, давайте предположим, что у меня есть механизм рендеринга, который предоставляется в виде библиотеки GCC engine.a. Эта библиотека содержит class Screen, который имеет метод void Screen::add(const Drawable & child). Все, что у меня есть, это заголовки и сама библиотека. В моем приложении я создаю экземпляр Screen, создаю несколько Drawable объектов и add их для Screen.

Мой вопрос:
Может ли моя цепочка инструментов GCC (или версия моей цепочки инструментов GCC) создать другуюмакет памяти для Drawable объектов, чем в скомпилированных engine.a? Стандарт не определяет его, и это деталь реализации. В любом случае это будет отлично связывать. Как я могу знать это и как я могу быть уверен в правильном поведении?

PS Я в основном использую набор инструментов ARM GCC для архитектуры Cortex-M. Но мой вопрос не ограничивается этим .

PPS Если у вас есть какие-либо мысли, связанные, но не связанные с GCC, пожалуйста, не стесняйтесь поделиться.

Спасибо.

РЕДАКТИРОВАТЬ
Этот вопрос касается ТОЛЬКО внутренних компонентов компилятора.

Ответы [ 2 ]

4 голосов
/ 31 октября 2019

Может ли моя цепочка инструментов GCC (или версия моей цепочки инструментов GCC) создать другую схему памяти для объектов Drawable, чем в скомпилированном engine.a?

Да. Рассмотрим следующий глупый пример:

struct Drawable
{
   #ifdef ENABLE_COUNTERS
   int counter = 0;
   #endif

  // ...
};

Возможно, один человек скомпилировал -DENABLE_COUNTERS, а кто-то другой - нет. Это нарушает правило единого определения. Или, возможно, была скомпилирована одна цепочка инструментов, где целые числа были 32-битными, а другая - с 64-битными.

Линкер, чтобы быть быстрым, не будет жаловаться;оно просто отбросит все, кроме одного определения, которое может привести к разным видам хаоса (вызовы виртуальных функций могут стать странными, так как смещения становятся неправильными).

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

gcc имеет flto-odr-type-merging и -Wodr, которые могут помочь вам при компиляции.

Google's ASAN также может проверить макеты памяти, чтобы убедиться, что они идентичны.


Относительно вашего редактирования только на внутренних компонентах компилятора.

Пожалуйста, обратитесь к руководству GCC по стабильности ABI: https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html

Грубо говоря. Каждая основная версия компилятора имеет новый ABI. Более поздние второстепенные выпуски с тем же основным выпуском почти всегда совместимы.

Вы можете контролировать, на какой ABI вы ориентируетесь -fabi-version

3 голосов
/ 31 октября 2019

Макет памяти, наряду со многими другими вещами, является частью ABI. Одной из других вещей является схема искажения имени. Хотя вам следует связывать только объекты, скомпилированные для одного и того же ABI, разработчики ABI стараются использовать другую схему искажения, чтобы случайное связывание объектов, скомпилированных с другим ABI, обычно приводило к неразрешенным символам.

GCC имеет флаг командной строки для управленияABI: -fabi-version, но ABI зависит также от некоторых других опций, таких как -fno-exceptions и, очевидно, стандартная реализация библиотеки для стандартных типов.

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