__inline из другой единицы компиляции

Тема в разделе "LANGS.C", создана пользователем cppasm, 3 апр 2009.

  1. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    cppasm
    Извини братан, не понял. ^) Только для чего нужно уметь это обрабатывать? По-моему нормальный компилятор, на дефолтовых настройках, должен предвидеть подобную коллизию.
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Каким образом?
    Юзаем либу, там есть функция Encode(), и у нас в коде тоже есть такая функций.
    Линкер ругнется на то, что 2 функции с одинаковыми именами.
    Всё верно.
     
  3. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    n0name
    Речь о функе в заголовочном файле.
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    cppasm

    Если я не ошибаюсь, то не важно, заинлайнит он функцию или нет. Сам кейворд inline подскажет линкеру, что это функция, пытающаяся быть inline, и для нее нужно использовать иные методы связывания имен. То есть линкер в курсе и ругаться не будет. Если я не ошибаюсь :) Попробуй.
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    _DEN_
    По-моему даже не обязательно юзать inline, на дефолтных настройках для таких функций это подразумевается.
     
  6. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Ты так ничего и не понял...
    Заголовочный файл подключается во многие *.с, и соответственно функция будет в каждом из них.
    Линкеру потом на картах таро выкинуть какую из них использовать?

    Не писал быть хоть ерунды... Что подразумевается?
    Есть три объектника: obj1.obj, obj2.obj, obj3.obj
    В первом есть доступная из вне функция my_func, во втором есть доступная из вне функция my_func (имя одинаковое).
    А третий использует внешнюю функцию my_func (extern).
    Вопрос - из какого модуля линкер должен взять эту функцию, obj1 или obj2?
    Ему монетку бросить?

    Да я уже попробовал. Не ругается.
    Кстати что интересно - функция эта наружу видна из всех объектников.
    И если в другом модуле её использовать как extern - она используется нормально.
    Просто компилятор помечает для линкера что возможно несколько реализаций, и линкер не ругается.
     
  7. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    что это меняет?
    После препроцессорной обработки это не будет иметь никакого значения.
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    cppasm
    >Заголовочный файл подключается во многие *.с, и соответственно функция будет в каждом из них.
    Конечно, мне это не дано.

    >Линкеру потом на картах таро выкинуть какую из них использовать?
    На это ограничений не накладывается.

    n0name
    Меняет то, что такие функции могут инлайнится компилятором.
     
  9. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    inline по сути - это дополнительный уровень разграничения между ф-циями, которые компилятор может заинлайнить, и теми, инлайн которых запрещён. Т.е. компилятору можно запретить инлайн:
    1. всех ф-ций (/Ob0)
    2. не inline ф-ций (/Ob1).
    3. никаких ф-ций (т.е. всё разрешить) (/Ob2).

    Единственным определённым следствием этого атрибута есть помещение ф-ции в COMDAT-сегмент, что позволяет иметь несколько определений этой ф-ции в разных obj. С этой точки зрения inline - это вроде __declspec(selectany) для данных.
     
  10. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    green - спасибо.
    Действительно так и есть.

    Резюме:
    Если функция инлайнится - она встаивается в код и тут всё ясно.
    Если же нет - в каждом модуле функция помещается в COMDAT сегмент, и при сборке линкер выбирает лишь один из них, остальные игнорирует (выбрасывает).
     
  11. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    cppasm
    Линкер может оставлять несколько определений inline-ф-ции, если она определена в нескольких obj и там же вызывается как ф-ция. Т.е. приоритет отдаётся реализации ф-ции из своего obj.
     
  12. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Ну это зависит от атрибутов сегмента COMDAT.
    Там есть варианты: выбирать любой, выбирать любой если содержимое одинаково, выбирать из своего файла, выбирать с бо'льшим размером.
    На практике я проверил - студия выбирает первый попавшийся, остальные выбрасывает.

    Кстати вопрос немного не в тему.
    У Intel C++ есть ключ для межфайлового инлайна (/Qipo).
    Т.е. он в состоянии инлайнить функции, реализованные в другом файле.
    По сути он из всех исходников склеивает один большой, и потом уже оптимизирует.
    А у Visual Studio есть что-нибудь подобное?
    На текущий момент у меня сделано просто:
     
  13. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    cppasm
    Да, ты прав.
    Однако, странно...
    Получается, что логика работы программы зависит от опций компиляции - логически идентичные вызовы ф-ции работают по-разному. Особо весёлый случай будет, если ф-ция частично заинлайнилась, а частично вызывается в пределах одного модуля. Интересно, что по этому поводу говорит Стандарт С++.
    ---
    А вот что говорит:
    Код (Text):
    1. An inline function shall be defined in every translation unit in which it is used and [u]shall have exactly the
    2. same definition in every case[/u]
    Значит всё ок, студия имеет право брать первое попавшееся определение.
    ---

    Да. /GL (compiler) + /LTCG (linker).
     
  14. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Спасибо, попробую.
     
  15. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Ещё заметил, что GDI+ заголовки помимо переходников к dll содержат и функции с кодом, которые не инлайнятся даже при /LTCG (видны в exe и olly по ctrl+F5 открывает соответсвующий .h), например, inline Image* Image::Clone. И никакой ругани при компиляции не наблюдается, хотя GdiPlus.h есно включён в кучу модулей.
     
  16. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Ну у неё же указан inline.
    Как уже выяснили - независимо от того встраивается функция объявленная как inline, или так и остаётся функцией, можно иметь несколько вариантов этой функции в объектниках.
    Линкер на это ругаться не будет - просто выберет первую попавшуюся, остальные выкинет.
    При этом в стандарте написано что реализации у всех дубликатов должны быть одинаковы.
    Это забота программиста.

    А насчёт того что код не встраивается с /LTCG - я тут потестировал.
    Она реально работает, т.е. код из других модулей инлайнит.
    Просто в студии критерии инлайна пересмотрели, и решает инлайнить она достаточно не часто.
    По крайней мере VC++ 6.0 SP6 Pro у меня гораздо агрессивнее инлайнит чем VS 2008 Express.
    А указать критерии инлайна (максимальный размер) ключами нельзя в отличии к примеру от Intel C++.