Wenn Sie denselben Code verwenden, ändert sich durch einfaches Ändern des Compilers (von einem C-Compiler zu einem C ++ - Compiler), wie viel Speicher zugewiesen wird. Ich bin mir nicht ganz sicher, warum das so ist und würde es gerne besser verstehen. Bisher ist die beste Antwort, die ich erhalten habe, "wahrscheinlich die E / A-Streams", was nicht sehr beschreibend ist und mich über den Aspekt "Sie zahlen nicht für das, was Sie nicht verwenden" in C ++ wundert.
Ich verwende die Clang- und GCC-Compiler, Versionen 7.0.1-8 und 8.3.0-6. Mein System läuft auf Debian 10 (Buster), spätestens. Die Benchmarks werden über das Valgrind-Massiv durchgeführt.
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
Der verwendete Code ändert sich nicht, aber ob ich als C oder als C ++ kompiliere, ändert die Ergebnisse des Valgrind-Benchmarks. Die Werte bleiben jedoch über alle Compiler hinweg konsistent. Die Laufzeitzuordnungen (Peak) für das Programm lauten wie folgt:
- GCC (C): 1.032 Bytes (1 KB)
- G ++ (C ++): 73.744 Bytes (~ 74 KB)
- Clang (C): 1.032 Bytes (1 KB)
- Clang ++ (C ++): 73.744 Bytes (~ 74 KB)
Zum Kompilieren verwende ich folgende Befehle:
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
Für Valgrind führe ich valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-lang
jeden Compiler und jede Sprache aus und ms_print
zeige dann die Peaks an.
Mache ich hier etwas falsch
quelle
try
Blocks auf Kosten eines größeren Speicherbedarfs, möglicherweise mit einer Sprungtabelle oder Ähnlichem, nicht beeinträchtigt wird. Versuchen Sie vielleicht ausnahmslos zu kompilieren und sehen Sie, welche Auswirkungen dies hat. Bearbeiten: Versuchen Sie iterativ, verschiedene C ++ - Funktionen zu deaktivieren, um festzustellen, welche Auswirkungen dies auf den Speicherbedarf hat.clang++ -xc
stattclang
war die gleiche Zuordnung vorhanden, was stark darauf hindeutet, dass es sich um verknüpfte Bibliotheken handeltC
Modus genau die gleiche Anzahl von Bytes und im Modus genau die gleiche Anzahl von Bytes erzeugenC++
. Haben Sie einen Transkriptionsfehler gemacht?Antworten:
Die Heap-Nutzung stammt aus der C ++ - Standardbibliothek. Es reserviert Speicher für die interne Bibliotheksnutzung beim Start. Wenn Sie nicht dagegen verlinken, sollte zwischen der C- und der C ++ - Version kein Unterschied bestehen. Mit GCC und Clang können Sie die Datei kompilieren mit:
Dadurch wird der Linker angewiesen, keine Verknüpfung mit nicht verwendeten Bibliotheken herzustellen. In Ihrem Beispielcode wird die C ++ - Bibliothek nicht verwendet, daher sollte sie nicht mit der C ++ - Standardbibliothek verknüpft werden.
Sie können dies auch mit der C-Datei testen. Wenn Sie kompilieren mit:
Die Heap-Nutzung wird wieder angezeigt, obwohl Sie ein C-Programm erstellt haben.
Die Verwendung des Heapspeichers hängt offensichtlich von der spezifischen Implementierung der C ++ - Bibliothek ab, die Sie verwenden. In Ihrem Fall ist dies die GNU C ++ - Bibliothek libstdc ++ . Andere Implementierungen weisen möglicherweise nicht die gleiche Speichermenge oder überhaupt keinen Speicher zu (zumindest nicht beim Start). Die LLVM C ++ - Bibliothek ( libc ++ ) führt beispielsweise beim Start keine Heap-Zuweisung durch, zumindest unter Linux Maschine:
Die Heap-Verwendung ist die gleiche, als würde man überhaupt nicht dagegen verlinken.
(Wenn die Kompilierung fehlschlägt, ist libc ++ wahrscheinlich nicht installiert. Der Paketname enthält normalerweise "libc ++" oder "libcxx".)
quelle
-Wl,--as-needed
Flag entfernt Bibliotheken, die Sie in Ihren-l
Flags angegeben haben, die Sie jedoch nicht verwenden. Wenn Sie also keine Bibliothek verwenden, verknüpfen Sie sie einfach nicht. Sie brauchen diese Flagge dafür nicht. Wenn Ihr Build-System jedoch zu viele Bibliotheken hinzufügt und es eine Menge Arbeit wäre, alle zu bereinigen und nur die benötigten zu verknüpfen, können Sie stattdessen dieses Flag verwenden. Die Standardbibliothek ist jedoch eine Ausnahme, da sie automatisch mit verknüpft wird. Das ist also ein Eckfall.Weder GCC noch Clang sind Compiler - sie sind tatsächlich Toolchain-Treiberprogramme. Das heißt, sie rufen den Compiler, den Assembler und den Linker auf.
Wenn Sie Ihren Code mit einem C- oder C ++ - Compiler kompilieren, wird dieselbe Assembly erstellt. Der Assembler erzeugt dieselben Objekte. Der Unterschied besteht darin, dass der Toolchain-Treiber für die beiden verschiedenen Sprachen unterschiedliche Eingaben für den Linker bereitstellt: unterschiedliche Starts (C ++ erfordert Code zum Ausführen von Konstruktoren und Destruktoren für Objekte mit statischer oder threadlokaler Speicherdauer auf Namespace-Ebene und Infrastruktur für den Stapel Frames zur Unterstützung des Abwickelns beispielsweise während der Ausnahmeverarbeitung), die C ++ - Standardbibliothek (die auch Objekte mit statischer Speicherdauer auf Namespace-Ebene enthält) und wahrscheinlich zusätzliche Laufzeitbibliotheken (z. B. libgcc mit seiner Stack-Abwicklungsinfrastruktur).
Kurz gesagt, es ist nicht der Compiler, der den Footprint vergrößert, sondern das Verknüpfen von Dingen, die Sie durch Auswahl der C ++ - Sprache verwendet haben.
Es ist wahr, dass C ++ die Philosophie "Nur für das bezahlen, was Sie verwenden" hat, aber wenn Sie die Sprache verwenden, zahlen Sie dafür. Sie können Teile der Sprache deaktivieren (RTTI, Ausnahmebehandlung), aber dann verwenden Sie C ++ nicht mehr. Wie in einer anderen Antwort erwähnt, können Sie den Treiber anweisen, dies wegzulassen, wenn Sie die Standardbibliothek überhaupt nicht verwenden (--Wl, - nach Bedarf), aber wenn Sie keine der Funktionen verwenden Warum wählen Sie in C ++ oder seiner Bibliothek überhaupt C ++ als Programmiersprache?
quelle