Почему начальное распределение C ++ намного больше, чем C? - PullRequest
135 голосов
/ 20 июня 2019

При использовании того же кода простое изменение компилятора (с компилятора C на компилятор C ++) изменит объем выделяемой памяти. Я не совсем уверен, почему это так и хотел бы понять это больше. Пока что лучший ответ, который я получил, это «вероятно, потоки ввода / вывода», который не очень описателен и заставляет меня задуматься о аспекте C ++ «вы не платите за то, что вы не используете».

Я использую компиляторы Clang и GCC, версии 7.0.1-8 и 8.3.0-6 соответственно. Моя система работает на Debian 10 (Buster), последняя версия. Тесты выполняются через массив Valgrind.

#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

Используемый код не изменяется, но независимо от того, компилируется ли я в C или C ++, он меняет результаты теста Valgrind. Однако значения остаются неизменными для разных компиляторов. Распределение времени выполнения (пиковое значение) для программы происходит следующим образом:

  • GCC (C): 1032 байта (1 КБ)
  • G ++ (C ++): 73 744 байта (~ 74 КБ)
  • Clang (C): 1032 байта (1 КБ)
  • Clang ++ (C ++): 73 744 байта (~ 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 для отображения пиков.

Я что-то здесь не так делаю?

Ответы [ 2 ]

149 голосов
/ 20 июня 2019

Использование кучи происходит из стандартной библиотеки C ++. Он выделяет память для внутреннего использования библиотеки при запуске. Если вы не ссылаетесь на него, между версиями C и C ++ не должно быть нулевой разницы. С GCC и Clang вы можете скомпилировать файл с помощью:

g++ -Wl,--as-needed main.cpp

Это даст указание компоновщику не связываться с неиспользуемыми библиотеками. В вашем примере кода библиотека C ++ не используется, поэтому она не должна ссылаться на стандартную библиотеку C ++.

Вы также можете проверить это с помощью файла C. Если вы компилируете с:

gcc main.c -lstdc++

Использование кучи снова появится, даже если вы создали программу на Си.

Использование кучи, очевидно, зависит от конкретной используемой вами реализации библиотеки C ++. В вашем случае это библиотека GNU C ++, libstdc ++ . Другие реализации могут не выделять такой же объем памяти или вообще не выделять какую-либо память (по крайней мере, не при запуске). Например, библиотека C ++ LLVM ( libc ++ ), например, не выполняет выделение кучи при запуске по крайней мере на моей машине с Linux:

clang++ -stdlib=libc++ main.cpp

Использование кучи - это то же самое, что вообще не связываться с ним.

(Если компиляция не удалась, возможно, libc ++ не установлен. Имя пакета обычно содержит «libc ++» или «libcxx».)

14 голосов
/ 21 июня 2019

Ни GCC, ни Clang не являются компиляторами - они на самом деле программы-драйверы инструментов. Это означает, что они вызывают компилятор, ассемблер и компоновщик.

Если вы скомпилируете свой код с помощью компилятора C или C ++, вы получите ту же самую сборку. Ассемблер будет производить те же объекты. Разница заключается в том, что драйвер цепочки инструментов будет обеспечивать разные входные данные для компоновщика для двух разных языков: разные стартапы (C ++ требует код для выполнения конструкторов и деструкторов для объектов со статическим или локальным потоком хранилища на уровне пространства имен и требует инфраструктуры для стека например, кадры для поддержки разматывания во время обработки исключений), стандартная библиотека C ++ (которая также имеет объекты статической длительности хранения на уровне пространства имен) и, возможно, дополнительные библиотеки времени выполнения (например, libgcc с его инфраструктурой разматывания стека).

Короче говоря, это не компилятор, вызывающий увеличение занимаемой площади, это связывание материалов, которые вы выбрали, выбрав язык C ++.

Это правда, что в C ++ есть философия «плати только за то, что ты используешь», но, используя язык, ты платишь за него. Вы можете отключить части языка (RTTI, обработка исключений), но тогда вы больше не используете C ++. Как упомянуто в другом ответе, если вы вообще не используете стандартную библиотеку, вы можете дать указание драйверу не указывать это (--Wl, - по мере необходимости), но если вы не собираетесь использовать какие-либо функции C ++ или его библиотеки, почему вы даже выбираете C ++ в качестве языка программирования?

...