Ссылался ли адрес C ++ 11 на передачу объектов std lib между границами динамической /разделяемой библиотеки? (т. е. dll и т. д.)?

Одна из моих основных жалоб на C ++ заключается в том, насколько сложно на практике передавать объекты библиотеки std за пределы границ динамической библиотеки (т. е. dll /so).

Библиотека std часто имеет только заголовок. Это отлично подходит для выполнения некоторых удивительных оптимизаций. Однако для dll они часто создаются с разными настройками компилятора, которые могут влиять на внутреннюю структуру /код контейнеров библиотеки std. Например, в MSVC одна dll может строить с отладкой итератора, а другая - с ее отключением. Эти две библиотеки dll могут столкнуться с проблемами, проходящими через контейнеры std. Если в моем интерфейсе я выставляю std::string, я не могу гарантировать код, который клиент использует для std::string является точным соответствием кода моей библиотеки> ---- +: = 2 =: + ----.

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

Мой вопрос в том, пытался ли C ++ 11 что-либо решить для решения этих проблем?

30 голосов | спросил Doug T. 21 32012vEurope/Moscow11bEurope/MoscowWed, 21 Nov 2012 17:47:59 +0400 2012, 17:47:59

3 ответа


16

Вы правы, что все STL - фактически, что-либо из любой сторонней библиотеки, которая является шаблоном - лучше всего избегать в любом открытом C ++ API. Вы также хотите следовать длинному списку правил на http: //www.ros .org /reps /rep-0009.html # definition , чтобы препятствовать потере ABI, что делает программирование общедоступными C ++ API сложными задачами.

И ответ о C ++ 11 - нет, этот стандарт не касается этого. Более интересно то, почему нет? Ответ заключается в том, что C ++ 17 очень трогательно, и для модулей C ++, которые нужно реализовать, нам нужны экспортированные шаблоны для работы, и для этого нам нужен компилятор типа LLVM, такой как clang, который может сбрасывать полный AST на диск, а затем выполняют зависящие от вызывающего запросы поисковые запросы для обработки множества случаев нарушения ODR в любом крупном проекте C ++, который, кстати, включает в себя множество кодов GCC и ELF.

Наконец, я вижу много комментариев о ненависти MSVC и про GCC. Они очень дезинформированы - GCC на ELF принципиально и безвозвратно не способен создать правильный и правильный код на C ++. Причин для этого много и легион, но я быстро приведу один пример: GCC на ELF не может безопасно создавать расширения Python, написанные с использованием Boost.Python, где в Python загружается более одного расширения на основе Boost.Python. Это потому, что ELF с его глобальной таблицей символов C просто неспособен по дизайну предотвращения нарушений ODR, вызывающих segfaults, тогда как PE и MachO и действительно предлагаемая спецификация C ++ Modules все используют таблицы символов для каждого модуля, что, кстати, также означает значительно более быстрое время инициализации процесса. И есть еще много проблем: см. Статью StackOverflow, на которую я недавно ответил: https: //stackoverflow.com/questions/14268736/symbol-visibility-exceptions-runtime-error/14364055#14364055 , например, где исключения C ++ исключений безвозвратно фундаментально нарушены на ELF.

Последний момент: в отношении взаимодействия разных STL это большая боль для многих крупных корпоративных пользователей, которые пытаются смешивать сторонние библиотеки, которые тесно интегрированы в реализацию STL. Единственное решение - это новый механизм для C ++ для взаимодействия с STL-интерфейсом, и, хотя они на нем, вы можете также исправить компилятор, чтобы вы могли (например) смешивать файлы MSVC, GCC и clang скомпилированных объектов, и все это просто работает , Я бы посмотрел на C ++ 17 и посмотрел, что там появится в ближайшие несколько лет - я был бы удивлен, если ничего не получится.

ответил Niall Douglas 17 Jpm1000000pmThu, 17 Jan 2013 20:58:38 +040013 2013, 20:58:38
8

В спецификации никогда не было этой проблемы. Это потому, что в нем есть концепция под названием «одно правило определения», в соответствии с которой каждый символ имеет ровно одно определение в текущем процессе.

Windows DLL нарушают это требование. Вот почему все эти проблемы. Таким образом, Microsoft может исправить это, а не комитет по стандартизации C ++. У Unix никогда не было этой проблемы, потому что совместно используемые библиотеки работают по-разному и по умолчанию соответствуют одному правилу определения (вы можете явно разбить его, но вы, очевидно, делаете это, только если знаете, что можете себе это позволить, и вам нужно выжать несколько лишних циклов).

Windows DLL нарушают одно правило определения, потому что:

  • Они жестко задают, из какой динамической библиотеки символ будет использоваться во время статического времени ссылки и статические символы решения в пределах библиотеки, которая их определяет. Поэтому, если один и тот же слабый символ генерируется в нескольких разделяемых библиотеках и в этих библиотеках, чем используется в одном процессе, динамический компоновщик не имеет шансов объединить эти символы. Обычно такие символы являются статическими или классовыми препятствиями экземпляров шаблона, и это вызывает проблемы при передаче экземпляров между кодом в разных DLL.
  • Они жестко задают, будет ли символ импортироваться из динамической библиотеки уже во время компиляции. Таким образом, код, связанный с некоторой библиотекой, статически несовместим с кодом, связанным с той же библиотекой, динамически.

Unix, использующий экспорт формата ELF, неявно импортирует все экспортированные символы, чтобы избежать первой проблемы, и не различает статически и динамически разрешенные символы до статического времени ссылки, чтобы избежать второго.


Другая проблема связана с флагами компилятора. Эта проблема существует для любой программы, состоящей из нескольких блоков компиляции, динамические библиотеки не обязательно должны быть задействованы. Однако в Windows это намного хуже. В Unix на самом деле неважно, ссылаетесь ли вы статически или динамически, никто никогда не связывает стандартную статичность в любом случае (в Linux это может быть даже незаконно), и нет специальной среды для отладки, поэтому одна сборка достаточно хороша. Но то, как Microsoft внедрила статическую и динамическую компоновку, отладки и выпуска времени выполнения и некоторые другие варианты, означает, что они вызвали комбинаторный взрыв необходимых вариантов библиотеки. Снова проблема с платформой, а не проблема языка C ++.

ответил Jan Hudec 21 32012vEurope/Moscow11bEurope/MoscowWed, 21 Nov 2012 18:52:41 +0400 2012, 18:52:41
7

Нет.

Продолжается работа над заменой системы заголовков, которая называется Модулями, и которая может повлиять на это, но, конечно, не большая.

ответил Klaim 21 32012vEurope/Moscow11bEurope/MoscowWed, 21 Nov 2012 19:05:11 +0400 2012, 19:05:11

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132