При использовании того же кода простая замена компилятора (с компилятора C на компилятор C ++) изменит объем выделяемой памяти. Я не совсем уверен, почему это так, и хотел бы понять это больше. Пока что лучший ответ, который я получил, - это «вероятно, потоки ввода-вывода», который не очень информативен и заставляет меня задаться вопросом об аспекте C ++ «вы не платите за то, что не используете».
Я использую компиляторы Clang и GCC версий 7.0.1-8 и 8.3.0-6 соответственно. Моя система работает на Debian 10 (Buster) последней версии. Тесты выполняются через Valgrind Massif.
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
Используемый код не меняется, но независимо от того, компилирую я как C или как C ++, он изменяет результаты теста Valgrind. Однако значения остаются неизменными для разных компиляторов. Распределение времени выполнения (пик) для программы выглядит следующим образом:
- GCC (C): 1032 байта (1 КБ)
- G ++ (C ++): 73744 байта (~ 74 КБ)
- Clang (C): 1032 байта (1 КБ)
- Clang ++ (C ++): 73744 байта (~ 74 КБ)
Для компиляции я использую следующие команды:
clang -O3 -o c-clang ./main.c
gcc -O3 -o c-gcc ./main.c
clang++ -O3 -o cpp-clang ./main.cpp
g++ -O3 -o cpp-gcc ./main.cpp
Что касается Valgrind, я использую valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-lang
каждый компилятор и язык, а затем ms_print
для отображения пиков.
Я что-то здесь делаю не так?
источник
try
блока за счет большего объема памяти, возможно, с таблицей переходов или чем-то еще. Может быть, попробуйте скомпилировать без исключений и посмотреть, какое влияние это окажет. Изменить: на самом деле, итеративно попробуйте отключить различные функции C ++, чтобы увидеть, какое влияние это оказывает на объем памяти.clang++ -xc
вместо былоclang
такое же распределение, что явно указывает на то, что это связано с подключенными библиотекамиC
режиме и такое же количество байтов вC++
режиме. Вы сделали ошибку при расшифровке?Ответы:
Использование кучи происходит из стандартной библиотеки C ++. Он выделяет память для использования внутренней библиотеки при запуске. Если вы не ссылаетесь на него, не должно быть никакой разницы между версиями C и C ++. С помощью GCC и Clang вы можете скомпилировать файл с помощью:
Это укажет компоновщику не связываться с неиспользуемыми библиотеками. В вашем примере кода библиотека C ++ не используется, поэтому она не должна связываться со стандартной библиотекой C ++.
Вы также можете проверить это с помощью файла C. Если вы компилируете с помощью:
Использование кучи снова появится, даже если вы создали программу C.
Использование кучи, очевидно, зависит от конкретной реализации библиотеки C ++, которую вы используете. В вашем случае это библиотека GNU C ++, libstdc ++ . Другие реализации могут не выделять такой же объем памяти или они могут вообще не выделять память (по крайней мере, не при запуске). Например, библиотека LLVM C ++ ( libc ++ ) не выделяет кучу при запуске, по крайней мере, в моем Linux машина:
Использование кучи - это то же самое, что и полное отсутствие ссылок на нее.
(Если компиляция не удалась, вероятно, libc ++ не установлена. Имя пакета обычно содержит «libc ++» или «libcxx».)
источник
-Wl,--as-needed
Флаг удаляет библиотеки, которые вы указываете в своих-l
флагах, но фактически не используете. Так что, если вы не используете библиотеку, просто не связывайтесь с ней. Для этого вам не нужен этот флаг. Однако, если ваша система сборки добавляет слишком много библиотек, и очистить их все и связать только те, которые необходимы, потребует много работы, тогда вы можете использовать этот флаг вместо этого. Стандартная библиотека является исключением, поскольку она автоматически связана с. Так что это угловой случай.Ни GCC, ни Clang не являются компиляторами - на самом деле это программы драйверов инструментальной цепочки. Это означает, что они вызывают компилятор, ассемблер и компоновщик.
Если вы скомпилируете свой код с помощью компилятора C или C ++, вы получите ту же сборку. Ассемблер создаст те же объекты. Разница в том, что драйвер инструментальной цепочки будет предоставлять разные входные данные компоновщику для двух разных языков: разные стартапы (C ++ требует код для выполнения конструкторов и деструкторов для объектов со статической или локальной продолжительностью хранения потока на уровне пространства имен и требует инфраструктуры для стека. фреймы для поддержки раскручивания во время обработки исключений, например), стандартная библиотека C ++ (которая также имеет объекты статической продолжительности хранения на уровне пространства имен) и, возможно, дополнительные библиотеки времени выполнения (например, libgcc с ее инфраструктурой раскрутки стека).
Короче говоря, увеличение занимаемой площади вызвано не компилятором, а связыванием того, что вы решили использовать, выбрав язык C ++.
Верно, что в C ++ существует философия «платить только за то, что вы используете», но, используя язык, вы платите за это. Вы можете отключить части языка (RTTI, обработка исключений), но тогда вы больше не используете C ++. Как упоминалось в другом ответе, если вы вообще не используете стандартную библиотеку, вы можете проинструктировать драйвер оставить это (--Wl, - по мере необходимости), но если вы не собираетесь использовать какие-либо функции C ++ или его библиотеки, почему вы вообще выбрали C ++ в качестве языка программирования?
источник