Компиляция встроенной функции

Я намерен обеспечить простые обертки для операционной системы API, которые бросают исключения, когда ошибки случаются. Эти обертки просты, и все они определяются как встроенные функции в заголовом файле. Поскольку System API должен быть большой, файл заголовка должен также быть огромным, содержащий большое количество крошечных встроенных функций. Проблема в том, что если общая библиотека (.so) скомпилирована с включенным файлом заголовка, все эти крошечные обертки будут скомпилированы в полученные двоичные двоичные, приводящие к большому двоичному файлу, даже когда только небольшая часть обертки на самом деле на самом деле использовал? Как насчет случая с исполняемыми файлами, это будет отличаться? Если это так, будет разделить обертки в несколько файлов заголовка, быть единственным решением? Или я должен сделать внутреннюю связь обертки, указав static?

Вот что я думаю. Упаковы могут быть использованы ODR (например, принимая его адрес). А на платформах Linux функции с внешним соединением экспортируются по умолчанию (I.E., связываемая другими двоичными модулями). Поэтому, я думаю, это может быть необходимо для линкера на самом деле генерировать определения контуров для них. См. пункт 3) в разделе Описание здесь.

Простой пример, упаковка CloseHandle() в Windows API:

inline void close_handle(HANDLE handle) {
  if (!CloseHandle(handle)) {
    throw std::system_error(GetLastError(), std::system_category(), "CloseHandle");
  }
}

person Lingxi    schedule 16.11.2015    source источник
comment
Мое чувство состоит в том, что ваш вопрос слишком широкий (вы не показывать какой-либо код), неясно, и вы слишком заботитесь о неявных деталях (вы не сказали, какие), что реализация работает довольно хорошо на практике. Сначала код немного библиотеки, затем спросите более целенаправленные вопросы с каким-то фактическим исходным кодом в них. Будьте более конкретными: какую ОС, какой компилятор, какие флаги компиляции, какой исходный код?   -  person Basile Starynkevitch    schedule 16.11.2015
comment
@Basilestarynkevitch вы можете быть правы. Но то, что я хочу, это (почти) защитное решение для исходного кода. Итак, детали опции OS, компилятора и компилятора не должны иметь значение. Я добавлю какой-то простой пример код.   -  person Lingxi    schedule 16.11.2015
comment
Параметры компилятора делают значение , поскольку некоторые компиляторы (g++, вероятно) не будут строить функции, если вы не просите их оптимизировать.   -  person Basile Starynkevitch    schedule 16.11.2015
comment
@Basilestarynkevitch На самом деле, мне не волнует, будут ли функции практически включены или нет. Я забочусь о том, генерируется ли двоичные данные, даже если функции вообще не используются. И если это так, то, что может быть элегантным и портативным способом предотвратить его.   -  person Lingxi    schedule 16.11.2015
comment
Вам не стоит заботиться о практике. Доверьтесь своей реализации, у нее достаточно хорошо. Я не понимаю, зачем избегать некоторой (редкой) включенной функции, которая должна быть изложена, настолько важна. Большинство обоснованных функций не будут изложены (и немногие, которые были изложены, будут изложены по некоторым веские причины)   -  person Basile Starynkevitch    schedule 16.11.2015
comment
Я наконец снизил вопрос. Вы не объясняете, почему вы спрашиваете, и что вы действительно боитесь. Мы не можем слепо догадаться. Вы должны мотивировать ваш вопрос гораздо больше. И вам нужно будет кодировать миллионы строк до размера кода.   -  person Basile Starynkevitch    schedule 16.11.2015
comment
Ваша библиотека вряд ли будет огромной, например Как Qt - это (вы пытались скомпилировать Qt самостоятельно?). Вы будете ниже, чем несколько сотен тысяч строк (вам нужно пять лет!) Так что ваши проблемы нереально   -  person Basile Starynkevitch    schedule 16.11.2015
comment
@Basilestarynkevitch да. Я просто слишком чувствителен над определенными вещами. Спасибо за обсуждение.   -  person Lingxi    schedule 16.11.2015


Ответы (1)


(Довольно небольшая) функция, объявленная static inline (или часто просто inline, или даже функция-член, определенная внутри некоторого class или struct), не будет (на практике) появляться в коде, если она не используется ( см это), и, вероятно, будет встраиваемой везде. Конечно, вам нужно включить оптимизацию в вашей команде Compilation. Итак, если вы используете GCC, скомпилируйте с помощью g++ -Wall -O2 (и вы можете добавить -fverbose-asm -S и заглянуть внутрь сгенерированного ассемблерного кода, чтобы чек).

Некоторые компиляторы (и, вероятно, g++) не будут встроить встроить, если не просят оптимизировать. А встраивание — это всегда оптимизация, которую компилятор может не выполнять в некоторых случаях (в частности, когда где-то хранится адрес этой функции)

Кстати, может показаться, что вы заново изобретаете структуру, аналогичную POCO или Qt. Вы рассматривали их вместо этого?

Кроме того, недавние реализации C ++ 11 (и C ++ 14) уже упаковывают значительную часть API ОС (в частности, стандартной C ++ Библиотека IO и C ++ Библиотека поддержки резьбы А совсем недавно C ++ 14 TS), часто уже используя исключения, так Лучшее плечо на них и используйте компилятор C ++ C ++ (для GCC, это означает GCC 5.2 в ноябре 2015 г.).

(Другими словами, код вашей вещи для C ++ 11 по крайней мере, не C ++ 98)

На Linux с gcc (или clang / llvm), если создать библиотеку, вы можете заинтересовать ссылку-оптимизацию (Compile & Link Библиотека с g++ -O2 -flto), Предкуренные заголовки, Видимость Функция атрибуты.

Что касается программных библиотек на Linux, прочитайте Библиотека программы Howto. Для общих библиотек прочитайте бумагу Дразма: Как написать общий Библиотеки и Это ответ.

На практике включенная функция в какой-то библиотеке часто не будет изложена в библиотеке, но в прикладной программе вызывает ее. Поэтому, если ваша общая библиотека Foo определяет в общедоступном заголовке <foo.h>

 inline int maxsq(int a, int b) {
    // you could add some conditional throw here...
    if (std::abs(a) < std::abs(b)) return b*b;
    else return a*a;
 }

Затем объектный код maxsq , вероятно, не появится внутри libfoo.so, но только в вашей программе (который #include <foo.h> в исходном коде), если это программа требует maxsq, чтобы быть изложенным, например, хранит адрес maxsq где-то (или если вы не просили достаточно оптимизаций).

Помните, что встроение всегда оптимизация, а какой-то компилятор может избежать его (даже для хороших причин деятельности) иногда. На практике TRUST Ваш компилятор (фактически ваша реализация C ++ также включает в себя линкер, который может «собрать мусор» Разделы).

person Basile Starynkevitch    schedule 16.11.2015
comment
Смотрите здесь для некоторого обсуждения static inline в C ++ - person M.M; 16.11.2015
comment
Я надеюсь найти портативное решение для исходного кода, которое работает без Twiddling с параметрами компилятора. Кроме того, то, что мне нужно проверить систему API, а не целая рамка. Итак, Poco или Qt не соответствует моим потребностям. Они оба очень милые, конечно :) - person Lingxi; 16.11.2015
comment
Вам не нужно варианты компилятора Twiddling. Но ИМХО, GCC бесполезно для производственного кода без -Wall (чтобы получить большинство предупреждений) и без -O2 получить оптимизацию, без которых производительность двоичной программы будет плохой - person Basile Starynkevitch; 16.11.2015
comment
Как насчет случая, когда встроенная функция используется ODR, например, когда его адрес принимается? Определение наброски должно быть обязательным в таких случаях, что скомпилировано в двоичный. И использование ODR может быть не очевидно. Это может появиться в другом двоичном модуле. - person Lingxi; 16.11.2015
comment
Компилятор необходим для обработки этого случая прозрачно. - person Basile Starynkevitch; 16.11.2015
comment
Итак, вернемся к моему вопросу. Если не указывать static и атрибуты функции видимости (которые являются расширениями компилятора), встроенные функции действительно приведут к двоичной инфляции при составлении общей библиотеки? - person Lingxi; 16.11.2015
comment
Это зависит и является особой реализацией. На практике вы должны доверять компилятору (и просить его оптимизировать), что делает довольно хорошо в целом. Будьте более конкретны в вашем вопросе (с некоторым фактическим кодом). Кроме того, большинство общих библиотек имеют какой-то код, который конкретное приложение не будет использовать (но что не используется, зависит от приложения) - person Basile Starynkevitch; 16.11.2015