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;
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
|
show 6 more comments
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
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 atry
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 withclang++ -xc
instead ofclang
, 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 inC
mode and the exact same number of bytesC++
mode. Did you make a transcription error?
– RonJohn
Jun 22 at 0:13
|
show 6 more comments
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
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
c++ c benchmarking
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 atry
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 withclang++ -xc
instead ofclang
, 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 inC
mode and the exact same number of bytesC++
mode. Did you make a transcription error?
– RonJohn
Jun 22 at 0:13
|
show 6 more comments
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 atry
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 withclang++ -xc
instead ofclang
, 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 inC
mode and the exact same number of bytesC++
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
|
show 6 more comments
2 Answers
2
active
oldest
votes
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".)
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
|
show 1 more comment
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?
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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".)
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
|
show 1 more comment
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".)
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
|
show 1 more comment
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".)
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".)
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
|
show 1 more comment
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
|
show 1 more comment
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?
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
add a comment |
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?
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
add a comment |
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?
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?
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 ofclang
, 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 bytesC++
mode. Did you make a transcription error?– RonJohn
Jun 22 at 0:13