Why is C++ initial allocation so much larger than C's?How to avoid unexpected memory allocationHow much faster is C++ than C#?Why do we need virtual functions in C++?Why should C++ programmers minimize use of 'new'?Why are elementwise additions much faster in separate loops than in a combined loop?Why is reading lines from stdin much slower in C++ than Python?Why is processing a sorted array faster than processing an unsorted array?Why should I use a pointer rather than the object itself?C++ code for testing the Collatz conjecture faster than hand-written assembly - why?C vs C++ compilation incompatibility - does not name a typeWhy is 2 * (i * i) faster than 2 * i * i in Java?

/etc/hosts not working

Bin Packing with Relational Penalization

If you kill a Solar Angel can you use its Slaying Longbow?

Transferring Data From One Table to Another Using Multiple Keys in ArcPy?

Why wasn't EBCDIC designed with contiguous alphanumeric characters?

"I am [the / an] owner of a bookstore"?

Can dual citizens open crypto exchange accounts where U.S. citizens are prohibited?

What is the proper markup for a Math operator in boldface?

Why would anyone even use a Portkey?

Does a return economy-class seat between London and San Francisco release 5.28 tonnes of CO2 equivalents?

Do home values typically rise and fall consistently across different price ranges?

Is it okay to fade a human face just to create some space to place important content over it?

What is the Japanese name for the conventional shoelace knot?

Missing root certificates on Windows Server 2016 (fresh install)

How do I create a new column in a dataframe from an existing column using conditions?

A* pathfinding algorithm too slow

What happens if a caster is surprised while casting a spell with a long casting time?

How does mmorpg store data?

Adjective for 'made of pus' or 'corrupted by pus' or something of something of pus

Why was Pan Am Flight 103 flying over Lockerbie?

How do I ask a good question about a topic I am not completely familiar with?

1991 (I think) Trek 850 MTB bottom bracket replacement. Maybe similar to 830?

Can European countries bypass the EU and make their own individual trade deal with the U.S.?

What do you call a notepad used to keep a record?



Why is C++ initial allocation so much larger than C's?


How to avoid unexpected memory allocationHow much faster is C++ than C#?Why do we need virtual functions in C++?Why should C++ programmers minimize use of 'new'?Why are elementwise additions much faster in separate loops than in a combined loop?Why is reading lines from stdin much slower in C++ than Python?Why is processing a sorted array faster than processing an unsorted array?Why should I use a pointer rather than the object itself?C++ code for testing the Collatz conjecture faster than hand-written assembly - why?C vs C++ compilation incompatibility - does not name a typeWhy is 2 * (i * i) faster than 2 * i * i in Java?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








103















When using the same code, simply changing the compiler (from a C compiler to a C++ compiler) will change how much memory is allocated. I'm not quite sure why this is and would like to understand it more. So far the best response I've gotten is "probably the I/O streams", which isn't very descriptive and makes me wonder about the "you don't pay for what you don't use" aspect of C++.



I'm using the Clang and GCC compilers, versions 7.0.1-8 and 8.3.0-6 respectively. My system is running on Debian 10 (Buster), latest. The benchmarks are done via Valgrind Massif.



#include <stdio.h>

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



The code used does not change, but whether I compile as C or as C++, it changes the results of the Valgrind benchmark. The values remain consistent across compilers, however. The runtime allocations (peak) for the program go as follows:



  • 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)

For compiling, I use the following commands:



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


For Valgrind, I run valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-lang on each compiler and language, then ms_print for displaying the peaks.



Am I doing something wrong here?










share|improve this question



















  • 11





    To begin with, how are you building? What options do you use? And how do you measure? How do you run Valgrind?

    – Some programmer dude
    Jun 20 at 18:45






  • 15





    If I remember correctly, modern C++ compilers have to an exception model where there is no performance hit to entering a try block at the expense of a larger memory footprint, maybe with a jump table or something. Maybe try compiling without exceptions and see what impact that has. Edit : In fact, iteratively try disabling various c++ features to see what impact that has on the memory footprint.

    – François Andrieux
    Jun 20 at 18:48







  • 3





    When compiling with clang++ -xc instead of clang, the same allocation was there, which strongly suggests its due to linked libraries

    – Justin
    Jun 20 at 18:51






  • 14





    @bigwillydos This is indeed C++, I do not see any part of the C++ specifications it breaks... Other than potentially including stdio.h rather than cstdio but this is allowed at least in older C++ version. What do you think is "malformed" in this program?

    – Vality
    Jun 21 at 3:34






  • 4





    I find it suspicious that those gcc and clang compilers generate the exact same number of bytes in C mode and the exact same number of bytes C++ mode. Did you make a transcription error?

    – RonJohn
    Jun 22 at 0:13

















103















When using the same code, simply changing the compiler (from a C compiler to a C++ compiler) will change how much memory is allocated. I'm not quite sure why this is and would like to understand it more. So far the best response I've gotten is "probably the I/O streams", which isn't very descriptive and makes me wonder about the "you don't pay for what you don't use" aspect of C++.



I'm using the Clang and GCC compilers, versions 7.0.1-8 and 8.3.0-6 respectively. My system is running on Debian 10 (Buster), latest. The benchmarks are done via Valgrind Massif.



#include <stdio.h>

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



The code used does not change, but whether I compile as C or as C++, it changes the results of the Valgrind benchmark. The values remain consistent across compilers, however. The runtime allocations (peak) for the program go as follows:



  • 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)

For compiling, I use the following commands:



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


For Valgrind, I run valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-lang on each compiler and language, then ms_print for displaying the peaks.



Am I doing something wrong here?










share|improve this question



















  • 11





    To begin with, how are you building? What options do you use? And how do you measure? How do you run Valgrind?

    – Some programmer dude
    Jun 20 at 18:45






  • 15





    If I remember correctly, modern C++ compilers have to an exception model where there is no performance hit to entering a try block at the expense of a larger memory footprint, maybe with a jump table or something. Maybe try compiling without exceptions and see what impact that has. Edit : In fact, iteratively try disabling various c++ features to see what impact that has on the memory footprint.

    – François Andrieux
    Jun 20 at 18:48







  • 3





    When compiling with clang++ -xc instead of clang, the same allocation was there, which strongly suggests its due to linked libraries

    – Justin
    Jun 20 at 18:51






  • 14





    @bigwillydos This is indeed C++, I do not see any part of the C++ specifications it breaks... Other than potentially including stdio.h rather than cstdio but this is allowed at least in older C++ version. What do you think is "malformed" in this program?

    – Vality
    Jun 21 at 3:34






  • 4





    I find it suspicious that those gcc and clang compilers generate the exact same number of bytes in C mode and the exact same number of bytes C++ mode. Did you make a transcription error?

    – RonJohn
    Jun 22 at 0:13













103












103








103


14






When using the same code, simply changing the compiler (from a C compiler to a C++ compiler) will change how much memory is allocated. I'm not quite sure why this is and would like to understand it more. So far the best response I've gotten is "probably the I/O streams", which isn't very descriptive and makes me wonder about the "you don't pay for what you don't use" aspect of C++.



I'm using the Clang and GCC compilers, versions 7.0.1-8 and 8.3.0-6 respectively. My system is running on Debian 10 (Buster), latest. The benchmarks are done via Valgrind Massif.



#include <stdio.h>

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



The code used does not change, but whether I compile as C or as C++, it changes the results of the Valgrind benchmark. The values remain consistent across compilers, however. The runtime allocations (peak) for the program go as follows:



  • 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)

For compiling, I use the following commands:



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


For Valgrind, I run valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-lang on each compiler and language, then ms_print for displaying the peaks.



Am I doing something wrong here?










share|improve this question
















When using the same code, simply changing the compiler (from a C compiler to a C++ compiler) will change how much memory is allocated. I'm not quite sure why this is and would like to understand it more. So far the best response I've gotten is "probably the I/O streams", which isn't very descriptive and makes me wonder about the "you don't pay for what you don't use" aspect of C++.



I'm using the Clang and GCC compilers, versions 7.0.1-8 and 8.3.0-6 respectively. My system is running on Debian 10 (Buster), latest. The benchmarks are done via Valgrind Massif.



#include <stdio.h>

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



The code used does not change, but whether I compile as C or as C++, it changes the results of the Valgrind benchmark. The values remain consistent across compilers, however. The runtime allocations (peak) for the program go as follows:



  • 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)

For compiling, I use the following commands:



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


For Valgrind, I run valgrind --tool=massif --massif-out-file=m_compiler_lang ./compiler-lang on each compiler and language, then ms_print for displaying the peaks.



Am I doing something wrong here?







c++ c benchmarking






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 13 hours ago









Peter Mortensen

14.2k19 gold badges88 silver badges115 bronze badges




14.2k19 gold badges88 silver badges115 bronze badges










asked Jun 20 at 18:43









RerumuRerumu

4831 gold badge3 silver badges8 bronze badges




4831 gold badge3 silver badges8 bronze badges







  • 11





    To begin with, how are you building? What options do you use? And how do you measure? How do you run Valgrind?

    – Some programmer dude
    Jun 20 at 18:45






  • 15





    If I remember correctly, modern C++ compilers have to an exception model where there is no performance hit to entering a try block at the expense of a larger memory footprint, maybe with a jump table or something. Maybe try compiling without exceptions and see what impact that has. Edit : In fact, iteratively try disabling various c++ features to see what impact that has on the memory footprint.

    – François Andrieux
    Jun 20 at 18:48







  • 3





    When compiling with clang++ -xc instead of clang, the same allocation was there, which strongly suggests its due to linked libraries

    – Justin
    Jun 20 at 18:51






  • 14





    @bigwillydos This is indeed C++, I do not see any part of the C++ specifications it breaks... Other than potentially including stdio.h rather than cstdio but this is allowed at least in older C++ version. What do you think is "malformed" in this program?

    – Vality
    Jun 21 at 3:34






  • 4





    I find it suspicious that those gcc and clang compilers generate the exact same number of bytes in C mode and the exact same number of bytes C++ mode. Did you make a transcription error?

    – RonJohn
    Jun 22 at 0:13












  • 11





    To begin with, how are you building? What options do you use? And how do you measure? How do you run Valgrind?

    – Some programmer dude
    Jun 20 at 18:45






  • 15





    If I remember correctly, modern C++ compilers have to an exception model where there is no performance hit to entering a try block at the expense of a larger memory footprint, maybe with a jump table or something. Maybe try compiling without exceptions and see what impact that has. Edit : In fact, iteratively try disabling various c++ features to see what impact that has on the memory footprint.

    – François Andrieux
    Jun 20 at 18:48







  • 3





    When compiling with clang++ -xc instead of clang, the same allocation was there, which strongly suggests its due to linked libraries

    – Justin
    Jun 20 at 18:51






  • 14





    @bigwillydos This is indeed C++, I do not see any part of the C++ specifications it breaks... Other than potentially including stdio.h rather than cstdio but this is allowed at least in older C++ version. What do you think is "malformed" in this program?

    – Vality
    Jun 21 at 3:34






  • 4





    I find it suspicious that those gcc and clang compilers generate the exact same number of bytes in C mode and the exact same number of bytes C++ mode. Did you make a transcription error?

    – RonJohn
    Jun 22 at 0:13







11




11





To begin with, how are you building? What options do you use? And how do you measure? How do you run Valgrind?

– Some programmer dude
Jun 20 at 18:45





To begin with, how are you building? What options do you use? And how do you measure? How do you run Valgrind?

– Some programmer dude
Jun 20 at 18:45




15




15





If I remember correctly, modern C++ compilers have to an exception model where there is no performance hit to entering a try block at the expense of a larger memory footprint, maybe with a jump table or something. Maybe try compiling without exceptions and see what impact that has. Edit : In fact, iteratively try disabling various c++ features to see what impact that has on the memory footprint.

– François Andrieux
Jun 20 at 18:48






If I remember correctly, modern C++ compilers have to an exception model where there is no performance hit to entering a try block at the expense of a larger memory footprint, maybe with a jump table or something. Maybe try compiling without exceptions and see what impact that has. Edit : In fact, iteratively try disabling various c++ features to see what impact that has on the memory footprint.

– François Andrieux
Jun 20 at 18:48





3




3





When compiling with clang++ -xc instead of clang, the same allocation was there, which strongly suggests its due to linked libraries

– Justin
Jun 20 at 18:51





When compiling with clang++ -xc instead of clang, the same allocation was there, which strongly suggests its due to linked libraries

– Justin
Jun 20 at 18:51




14




14





@bigwillydos This is indeed C++, I do not see any part of the C++ specifications it breaks... Other than potentially including stdio.h rather than cstdio but this is allowed at least in older C++ version. What do you think is "malformed" in this program?

– Vality
Jun 21 at 3:34





@bigwillydos This is indeed C++, I do not see any part of the C++ specifications it breaks... Other than potentially including stdio.h rather than cstdio but this is allowed at least in older C++ version. What do you think is "malformed" in this program?

– Vality
Jun 21 at 3:34




4




4





I find it suspicious that those gcc and clang compilers generate the exact same number of bytes in C mode and the exact same number of bytes C++ mode. Did you make a transcription error?

– RonJohn
Jun 22 at 0:13





I find it suspicious that those gcc and clang compilers generate the exact same number of bytes in C mode and the exact same number of bytes C++ mode. Did you make a transcription error?

– RonJohn
Jun 22 at 0:13












2 Answers
2






active

oldest

votes


















125














The heap usage comes from the C++ standard library. It allocates memory for internal library use on startup. If you don't link against it, there should be zero difference between the C and C++ version. With GCC and Clang, you can compile the file with:




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


This will instruct the linker to not link against unused libraries. In your example code, the C++ library is not used, so it should not link against the C++ standard library.



You can also test this with the C file. If you compile with:




gcc main.c -lstdc++


The heap usage will reappear, even though you've built a C program.



The heap use is obviously dependant to the specific C++ library implementation you're using. In your case, that's the GNU C++ library, libstdc++. Other implementations might not allocate the same amount of memory, or they might not allocate any memory at all (at least not on startup.) The LLVM C++ library (libc++) for example does not do heap allocation on startup, at least on my Linux machine:




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


The heap use is the same as not linking at all against it.



(If compilation fails, then libc++ is probably not installed. The package name usually contains "libc++" or "libcxx".)






share|improve this answer




















  • 46





    On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

    – Nat
    Jun 21 at 3:48






  • 4





    @Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

    – DarcyThomas
    Jun 21 at 5:04






  • 20





    @Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

    – Nikos C.
    Jun 21 at 7:03






  • 34





    @Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

    – Norbert Lange
    Jun 21 at 8:16






  • 3





    @NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

    – Norbert Lange
    Jun 21 at 9:04


















8














Neither GCC nor Clang are compilers -- they're actually toolchain driver programs. That means they invoke the compiler, the assembler, and the linker.



If you compile your code with a C or a C++ compiler you will get the same assembly produced. The Assembler will produce the same objects. The difference is that the toolchain driver will provide different input to the linker for the two different languages: different startups (C++ requires code for executing constructors and destructors for objects with static or thread-local storage duration at namespace level, and requires infrastructure for stack frames to support unwinding during exception processing, for example), the C++ standard library (which also has objects of static storage duration at namespace level), and probably additional runtime libraries (for example, libgcc with its stack-unwinding infrastructure).



In short, it's not the compiler causing the increase in footprint, it's the linking in of stuff you've chose to use by choosing the C++ language.



It's true that C++ has the "pay only for what you use" philosophy, but by using the language, you pay for it. You can disable parts of the language (RTTI, exception handling) but then you're not using C++ any more. As mentioned in another answer, if you don't use the standard library at all you can instruct the driver to leave that out (--Wl,--as-needed) but if you're not going to use any of the features of C++ or its library, why are you even choosing C++ as a programming language?






share|improve this answer


















  • 10





    "but by using the language, you pay for it." If that were true the phrase would have no meaning...

    – Rakete1111
    Jun 21 at 17:14











  • The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

    – Peter Cordes
    yesterday














Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56692117%2fwhy-is-c-initial-allocation-so-much-larger-than-cs%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









125














The heap usage comes from the C++ standard library. It allocates memory for internal library use on startup. If you don't link against it, there should be zero difference between the C and C++ version. With GCC and Clang, you can compile the file with:




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


This will instruct the linker to not link against unused libraries. In your example code, the C++ library is not used, so it should not link against the C++ standard library.



You can also test this with the C file. If you compile with:




gcc main.c -lstdc++


The heap usage will reappear, even though you've built a C program.



The heap use is obviously dependant to the specific C++ library implementation you're using. In your case, that's the GNU C++ library, libstdc++. Other implementations might not allocate the same amount of memory, or they might not allocate any memory at all (at least not on startup.) The LLVM C++ library (libc++) for example does not do heap allocation on startup, at least on my Linux machine:




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


The heap use is the same as not linking at all against it.



(If compilation fails, then libc++ is probably not installed. The package name usually contains "libc++" or "libcxx".)






share|improve this answer




















  • 46





    On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

    – Nat
    Jun 21 at 3:48






  • 4





    @Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

    – DarcyThomas
    Jun 21 at 5:04






  • 20





    @Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

    – Nikos C.
    Jun 21 at 7:03






  • 34





    @Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

    – Norbert Lange
    Jun 21 at 8:16






  • 3





    @NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

    – Norbert Lange
    Jun 21 at 9:04















125














The heap usage comes from the C++ standard library. It allocates memory for internal library use on startup. If you don't link against it, there should be zero difference between the C and C++ version. With GCC and Clang, you can compile the file with:




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


This will instruct the linker to not link against unused libraries. In your example code, the C++ library is not used, so it should not link against the C++ standard library.



You can also test this with the C file. If you compile with:




gcc main.c -lstdc++


The heap usage will reappear, even though you've built a C program.



The heap use is obviously dependant to the specific C++ library implementation you're using. In your case, that's the GNU C++ library, libstdc++. Other implementations might not allocate the same amount of memory, or they might not allocate any memory at all (at least not on startup.) The LLVM C++ library (libc++) for example does not do heap allocation on startup, at least on my Linux machine:




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


The heap use is the same as not linking at all against it.



(If compilation fails, then libc++ is probably not installed. The package name usually contains "libc++" or "libcxx".)






share|improve this answer




















  • 46





    On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

    – Nat
    Jun 21 at 3:48






  • 4





    @Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

    – DarcyThomas
    Jun 21 at 5:04






  • 20





    @Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

    – Nikos C.
    Jun 21 at 7:03






  • 34





    @Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

    – Norbert Lange
    Jun 21 at 8:16






  • 3





    @NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

    – Norbert Lange
    Jun 21 at 9:04













125












125








125







The heap usage comes from the C++ standard library. It allocates memory for internal library use on startup. If you don't link against it, there should be zero difference between the C and C++ version. With GCC and Clang, you can compile the file with:




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


This will instruct the linker to not link against unused libraries. In your example code, the C++ library is not used, so it should not link against the C++ standard library.



You can also test this with the C file. If you compile with:




gcc main.c -lstdc++


The heap usage will reappear, even though you've built a C program.



The heap use is obviously dependant to the specific C++ library implementation you're using. In your case, that's the GNU C++ library, libstdc++. Other implementations might not allocate the same amount of memory, or they might not allocate any memory at all (at least not on startup.) The LLVM C++ library (libc++) for example does not do heap allocation on startup, at least on my Linux machine:




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


The heap use is the same as not linking at all against it.



(If compilation fails, then libc++ is probably not installed. The package name usually contains "libc++" or "libcxx".)






share|improve this answer















The heap usage comes from the C++ standard library. It allocates memory for internal library use on startup. If you don't link against it, there should be zero difference between the C and C++ version. With GCC and Clang, you can compile the file with:




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


This will instruct the linker to not link against unused libraries. In your example code, the C++ library is not used, so it should not link against the C++ standard library.



You can also test this with the C file. If you compile with:




gcc main.c -lstdc++


The heap usage will reappear, even though you've built a C program.



The heap use is obviously dependant to the specific C++ library implementation you're using. In your case, that's the GNU C++ library, libstdc++. Other implementations might not allocate the same amount of memory, or they might not allocate any memory at all (at least not on startup.) The LLVM C++ library (libc++) for example does not do heap allocation on startup, at least on my Linux machine:




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


The heap use is the same as not linking at all against it.



(If compilation fails, then libc++ is probably not installed. The package name usually contains "libc++" or "libcxx".)







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 days ago

























answered Jun 20 at 19:08









Nikos C.Nikos C.

39.4k6 gold badges46 silver badges75 bronze badges




39.4k6 gold badges46 silver badges75 bronze badges







  • 46





    On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

    – Nat
    Jun 21 at 3:48






  • 4





    @Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

    – DarcyThomas
    Jun 21 at 5:04






  • 20





    @Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

    – Nikos C.
    Jun 21 at 7:03






  • 34





    @Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

    – Norbert Lange
    Jun 21 at 8:16






  • 3





    @NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

    – Norbert Lange
    Jun 21 at 9:04












  • 46





    On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

    – Nat
    Jun 21 at 3:48






  • 4





    @Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

    – DarcyThomas
    Jun 21 at 5:04






  • 20





    @Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

    – Nikos C.
    Jun 21 at 7:03






  • 34





    @Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

    – Norbert Lange
    Jun 21 at 8:16






  • 3





    @NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

    – Norbert Lange
    Jun 21 at 9:04







46




46





On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

– Nat
Jun 21 at 3:48





On seeing this answer, my first thought is, "If this flag helps reduce unneeded overhead, why isn't it on by default?". Is there a good answer to that?

– Nat
Jun 21 at 3:48




4




4





@Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

– DarcyThomas
Jun 21 at 5:04





@Nat My guess is at dev time it is slower to compile. When you are ready to create a release build you would turn it on then. Also in a normal/large codebase the difference may be minimal (if you are using lots of the STD library etc.)

– DarcyThomas
Jun 21 at 5:04




20




20





@Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

– Nikos C.
Jun 21 at 7:03





@Nat The -Wl,--as-needed flag removes libraries that you specify in your -l flags but you're not actually using. So if you don't use a library, then just don't link against it. You don't need this flag for this. However, if your build system adds too many libraries and it would be a lot of work to clean them all up and only link those needed, then you can use this flag instead. The standard library is an exception though, since it's automatically linked against. So this is a corner case.

– Nikos C.
Jun 21 at 7:03




34




34





@Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

– Norbert Lange
Jun 21 at 8:16





@Nat --as-needed can have unwanted sideeffects, it works by checking whether you use any symbol of a library and kicks those out that fail the test. BUT: a library could also do various things implicitly, for example, if you have a static C++ instance in the library then its constructor will be automatically called. There are rare cases where a library you dont explicitly call into is necessary, but they exist.

– Norbert Lange
Jun 21 at 8:16




3




3





@NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

– Norbert Lange
Jun 21 at 9:04





@NikosC. Buildsystems do not know automatically which symbols your application uses, and which libraries implement them (varies between compilers, archs, distros and c/c++ libraries). Getting that right is rather troublesome, atleast for the base runtime libraries. But for the rare cases you need a library, you should simply use --no-as-needed for that one, and leave --as-needed everywhere else. A usecase I seen is libraries for tracing/debugging (lttng) and libraries that do something of the sort of authenticating/connecting.

– Norbert Lange
Jun 21 at 9:04













8














Neither GCC nor Clang are compilers -- they're actually toolchain driver programs. That means they invoke the compiler, the assembler, and the linker.



If you compile your code with a C or a C++ compiler you will get the same assembly produced. The Assembler will produce the same objects. The difference is that the toolchain driver will provide different input to the linker for the two different languages: different startups (C++ requires code for executing constructors and destructors for objects with static or thread-local storage duration at namespace level, and requires infrastructure for stack frames to support unwinding during exception processing, for example), the C++ standard library (which also has objects of static storage duration at namespace level), and probably additional runtime libraries (for example, libgcc with its stack-unwinding infrastructure).



In short, it's not the compiler causing the increase in footprint, it's the linking in of stuff you've chose to use by choosing the C++ language.



It's true that C++ has the "pay only for what you use" philosophy, but by using the language, you pay for it. You can disable parts of the language (RTTI, exception handling) but then you're not using C++ any more. As mentioned in another answer, if you don't use the standard library at all you can instruct the driver to leave that out (--Wl,--as-needed) but if you're not going to use any of the features of C++ or its library, why are you even choosing C++ as a programming language?






share|improve this answer


















  • 10





    "but by using the language, you pay for it." If that were true the phrase would have no meaning...

    – Rakete1111
    Jun 21 at 17:14











  • The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

    – Peter Cordes
    yesterday
















8














Neither GCC nor Clang are compilers -- they're actually toolchain driver programs. That means they invoke the compiler, the assembler, and the linker.



If you compile your code with a C or a C++ compiler you will get the same assembly produced. The Assembler will produce the same objects. The difference is that the toolchain driver will provide different input to the linker for the two different languages: different startups (C++ requires code for executing constructors and destructors for objects with static or thread-local storage duration at namespace level, and requires infrastructure for stack frames to support unwinding during exception processing, for example), the C++ standard library (which also has objects of static storage duration at namespace level), and probably additional runtime libraries (for example, libgcc with its stack-unwinding infrastructure).



In short, it's not the compiler causing the increase in footprint, it's the linking in of stuff you've chose to use by choosing the C++ language.



It's true that C++ has the "pay only for what you use" philosophy, but by using the language, you pay for it. You can disable parts of the language (RTTI, exception handling) but then you're not using C++ any more. As mentioned in another answer, if you don't use the standard library at all you can instruct the driver to leave that out (--Wl,--as-needed) but if you're not going to use any of the features of C++ or its library, why are you even choosing C++ as a programming language?






share|improve this answer


















  • 10





    "but by using the language, you pay for it." If that were true the phrase would have no meaning...

    – Rakete1111
    Jun 21 at 17:14











  • The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

    – Peter Cordes
    yesterday














8












8








8







Neither GCC nor Clang are compilers -- they're actually toolchain driver programs. That means they invoke the compiler, the assembler, and the linker.



If you compile your code with a C or a C++ compiler you will get the same assembly produced. The Assembler will produce the same objects. The difference is that the toolchain driver will provide different input to the linker for the two different languages: different startups (C++ requires code for executing constructors and destructors for objects with static or thread-local storage duration at namespace level, and requires infrastructure for stack frames to support unwinding during exception processing, for example), the C++ standard library (which also has objects of static storage duration at namespace level), and probably additional runtime libraries (for example, libgcc with its stack-unwinding infrastructure).



In short, it's not the compiler causing the increase in footprint, it's the linking in of stuff you've chose to use by choosing the C++ language.



It's true that C++ has the "pay only for what you use" philosophy, but by using the language, you pay for it. You can disable parts of the language (RTTI, exception handling) but then you're not using C++ any more. As mentioned in another answer, if you don't use the standard library at all you can instruct the driver to leave that out (--Wl,--as-needed) but if you're not going to use any of the features of C++ or its library, why are you even choosing C++ as a programming language?






share|improve this answer













Neither GCC nor Clang are compilers -- they're actually toolchain driver programs. That means they invoke the compiler, the assembler, and the linker.



If you compile your code with a C or a C++ compiler you will get the same assembly produced. The Assembler will produce the same objects. The difference is that the toolchain driver will provide different input to the linker for the two different languages: different startups (C++ requires code for executing constructors and destructors for objects with static or thread-local storage duration at namespace level, and requires infrastructure for stack frames to support unwinding during exception processing, for example), the C++ standard library (which also has objects of static storage duration at namespace level), and probably additional runtime libraries (for example, libgcc with its stack-unwinding infrastructure).



In short, it's not the compiler causing the increase in footprint, it's the linking in of stuff you've chose to use by choosing the C++ language.



It's true that C++ has the "pay only for what you use" philosophy, but by using the language, you pay for it. You can disable parts of the language (RTTI, exception handling) but then you're not using C++ any more. As mentioned in another answer, if you don't use the standard library at all you can instruct the driver to leave that out (--Wl,--as-needed) but if you're not going to use any of the features of C++ or its library, why are you even choosing C++ as a programming language?







share|improve this answer












share|improve this answer



share|improve this answer










answered Jun 21 at 13:23









Stephen M. WebbStephen M. Webb

1,0285 silver badges10 bronze badges




1,0285 silver badges10 bronze badges







  • 10





    "but by using the language, you pay for it." If that were true the phrase would have no meaning...

    – Rakete1111
    Jun 21 at 17:14











  • The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

    – Peter Cordes
    yesterday













  • 10





    "but by using the language, you pay for it." If that were true the phrase would have no meaning...

    – Rakete1111
    Jun 21 at 17:14











  • The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

    – Peter Cordes
    yesterday








10




10





"but by using the language, you pay for it." If that were true the phrase would have no meaning...

– Rakete1111
Jun 21 at 17:14





"but by using the language, you pay for it." If that were true the phrase would have no meaning...

– Rakete1111
Jun 21 at 17:14













The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

– Peter Cordes
yesterday






The fact that enabling exception handling has a cost even if you don't actually use it is a problem. That's not normal for C++ features in general, and it's something that the C++ standards working groups are trying to think of ways to fix. See Herb Sutter's keynote talk at ACCU 2019 De-fragmenting C++: Making exceptions more affordable and usable. It is an unfortunate fact, though, in current C++. And traditional C++ exceptions will probably always have that cost, even if/when new mechanisms for new exceptions are added with a keyword.

– Peter Cordes
yesterday


















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56692117%2fwhy-is-c-initial-allocation-so-much-larger-than-cs%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

Circuit construction for execution of conditional statements using least significant bitHow are two different registers being used as “control”?How exactly is the stated composite state of the two registers being produced using the $R_zz$ controlled rotations?Efficiently performing controlled rotations in HHLWould this quantum algorithm implementation work?How to prepare a superposed states of odd integers from $1$ to $sqrtN$?Why is this implementation of the order finding algorithm not working?Circuit construction for Hamiltonian simulationHow can I invert the least significant bit of a certain term of a superposed state?Implementing an oracleImplementing a controlled sum operation

Magento 2 “No Payment Methods” in Admin New OrderHow to integrate Paypal Express Checkout with the Magento APIMagento 1.5 - Sales > Order > edit order and shipping methods disappearAuto Invoice Check/Money Order Payment methodAdd more simple payment methods?Shipping methods not showingWhat should I do to change payment methods if changing the configuration has no effects?1.9 - No Payment Methods showing upMy Payment Methods not Showing for downloadable/virtual product when checkout?Magento2 API to access internal payment methodHow to call an existing payment methods in the registration form?