Во-первых, ваш пример кода неверен.Внимательно прочитайте стандарт C11 n1570 .Если вы хотите использовать стандарт malloc
, вам следует #include <stdlib.h>
.
В C ++ 11 (читается n3337 ) malloc
осуждаетсяи не должен использоваться (предпочитайте new
).Если вы все еще хотите использовать std::malloc
в C ++, вы должны #include <cstdlib>
(который в GCC включает в себя <stdlib.h>
)
Тогда ваш пример кода почти код C (после замены auto
на void*
), а не на C ++.Это может быть оптимизировано (если вы включите <stdlib.h>
), даже без -flto
, но только с -O3
, согласно правилу как если бы , в пустую main
.(Я даже написал публичный отчет, bismon-chariot-doc.pdf , в котором есть раздел §1.4.2, объясняющий на нескольких страницах, как происходит такая оптимизация).
Для оптимизацииоколо malloc
и free
, GCC использует некоторый __attribute__(malloc)
атрибут функции в объявлении (внутри <stdlib.h>
) malloc
.
Как -fltoмашиностроение работает?
Он работает с использованием некоторых внутренних ( GIMPLE -подобных и / или SSA -подобное) представление кода как во время «компиляции», так и во время «линковки» (на самом деле шаг компоновки становится другой компиляцией с оптимизацией всей программы, поэтому ваш код на практике дважды «компилируется»).
LTO всегда следует (на практике) использовать с некоторым флагом оптимизации (например, -O2
или даже -O3
) как во время компиляции, так и во время компоновки.Таким образом, вы должны скомпилировать и связать с g++ -flto -O2
(нет практического смысла использовать -flto
без как минимум -O2
и точно такую же оптимизациюфлаги должны использоваться при компиляции и во время компоновки).
Точнее -flto
также встраивает в объектные файлы некоторое внутреннее ( GIMPLE -подобное) представление исходного кода, и этотакже используется «во время соединения» (в частности, для оптимизации и вставки происходит снова при «связывании» вашей всей программы с повторным использованием ее GIMPLE).На самом деле GCC содержит некоторый внешний интерфейс LTO и компилятор с именем lto1
(в дополнение к внешнему интерфейсу C ++ и компилятору с именем cc1plus
) и lto1
(когда вы связываете с g++ -flto -O2
)используется во время соединения для повторной обработки этих представлений GIMPLE.
Возможно, libjemalloc
имеет свои собственные заголовки и может иметь inline
(или встроенные) функции.Затем вам также нужно использовать -flto -O2
при компиляции этой библиотеки из ее исходного кода (чтобы ее Gimple сохранялся в библиотеке)
Наконец, тот факт, что вызывается обычный malloc
, не зависит от-flto
.Это проблема компоновщика, а не компилятора.Вы можете попытаться связать -ljemalloc
статически (и тогда вам лучше собрать эту библиотеку также с gcc -flto -O2
; если вы не создадите ее таким образом, вы не получите оптимизацию LTO для вызовов malloc
).
Вы также можете передать -v
командам компиляции и компоновки, чтобы понять, что делает g++
.Вы могли бы даже передать -Wl,--verbose
, чтобы попросить ld
(начатый с g++
) быть многословным.
Обратите внимание, что LTO (и его внутренние представления) зависят от компилятора и версии.Внутреннее (Gimple & SSA ) представление немного отличается от GCC 7 & GCC 8 (а в Clang это очень отличается, поэтому, конечно, несовместимо).Динамический компоновщик ld-linux (8) не знает о LTO.
PS.Вы можете установить пакет libjemalloc-dev
и добавить #include <jemalloc/jemalloc.h>
в свой код.Смотрите также jemalloc (3) справочная страница.Возможно, libjemalloc
можно настроить или исправить, чтобы определить символ je_malloc
вместо malloc
.Тогда было бы проще (для LTO) использовать je_malloc
в вашем коде (чтобы избежать конфликта между несколькими malloc
ELF символами).Чтобы узнать больше о символах в общих библиотеках, прочитайте статью Дреппера Как писать общие библиотеки .И, конечно, вы должны ожидать, что LTO изменит поведение линковки!