Back to Basics: Compiling and Linking - Ben Saks - CppCon 2021

preview_player
Показать описание
---

Most C and C++ programmers know the conventions for distributing declarations and definitions among headers and source files. However, there are exceptions to these conventions that we often chalk up to “linker magic”. If the linker can’t deal with multiply-defined symbols, how does it handle inline and constexpr functions? Why do explicit template specializations go into source files when most template code goes into headers? And what can embedded developers do to tell the linker to map certain code and data into specific memory regions?

This session answers these questions by taking a detailed look at how the traditional C/C++ build model works with headers and source files. It describes what happens during each stage of the build process: preprocessing, compiling, instantiation, and linking. It explains what information the compiler records from declarations and definitions – including exceptional cases like inline and templates – and how the linker uses that information to generate an executable. It also shows how you can use explicit instantiation to control memory layout and reduce build times. Finally, this session walks an example program through the entire build process to demonstrate how everything fits together.

This is **not** a session on C++20 Modules. However, it explains terms such as “translation unit” and “linkage” that are also part of the Modules framework, providing a solid foundation for understanding Modules.

---
Ben Saks

---

Рекомендации по теме
Комментарии
Автор

Finally someone with GOOD info, without the colossal attitude & ego! This kind of practical info is exactly why I watch these cpp videos. Thank you Ben!

RunningSwimmingMan
Автор

these basics are that kind of information that changes the way you think about your code process. Thanks!

paoloose
Автор

Finally an understandable and comprehensive explanation! Thank you for this presentation.

CharlieScarver
Автор

This video was hugely helpful for me. Thanks a lot!

SurfinScientist
Автор

This is such a great talk. I was really struggling to understand how headers, compilation units and linkers work when I was starting out with C++, and spent so much time dealing with these errors as my programs were growing and started cross-referencing everything in the project. Especially when coming from "easier" languages where all this is completely hidden from the user. This should be one of the first videos people should watch!

One thing I felt missing from the talk is any mention of precompiled headers and what pros and cons they have. And also with all the stuff Ben flew past at the end I feel like this really needs a part 2 :)

nothke
Автор

Extremally informative and great presentation. thank you for the efforts. Thank you Ben and CppCon.

vikaskumarsharma
Автор

Great presentation. I learn a lot from watching it.

kamilziemian
Автор

Cool talk with good material to start with! Thanks!

PUZORS
Автор

This guy is very articulate and good at teaching

colin
Автор

I must have misunderstood sth, cannot comprehend the second item on slide 37(37:50). How is it possible not violating *ODR* by just _"defining the entity in a single header that doesn't depend on including other headers"_ ? I test it in my MSVS with C++20 and get error. It is either possible using *inline* keyword denoting _the same entity_ for all translation units or *static* keyword for _different entities_ for each translation unit, afaik.

berktopbas
Автор

Good job. You had a lot of ground to cover there, and got through it quite admirably.

jimwinchester
Автор

At 33:51, the function g was forward declared in b.o object file and defined in c.o. Is this acceptable? It doesn't have a extern keyword as well.
If this is acceptable does the linker look for a particular function definition across all the available obj files before throwing undefined function error.

shameelgoldentrio
Автор

Yeah, I knew about the problem of huge compilation times arising from the same stuff generated from the same template in multiple object file and then linker removing the duplicates. Now I see that apart from longer compile times it is also dangerous in some cases, because the linker just picks any definition and does not have to care if they are actually the same. And if it does care it would increase the compilation times even further. So it is quite easy to introduce some UB by accident. Defining explicit specializations and using extern in the header file fore them solves both issues. This is an obvious solution for an experienced dev, but still it needs to be seen at least once to understand that that's the way! Thanks for reminding us the basics and pointing out to this very common example, where things can be made better just with a little effort. I wonder if that's the reason chromium takes forever to compile with regular(non-jumbo) build on Linux.

linuxgaminginfullhdfps
Автор

@7:35 Maybe I'm misunderstanding what's going on here, but seems to me that the main reason not to define functions in header files is NOT that it slows the build process, but rather that it (almost always) BREAKS the build process, because it inevitably causes violations of the one definition rule down the line EVEN THOUGH you use #include guards.

To see why such a violation would usually arise, imagine there is a library X that supplies function f. Furthermore, suppose libraries A and B use X. To do this, they would #include "x.h". You'll probably be able to compile A and B just fine (without violating ODR) thanks to #include guards, but if application K uses A and B, when you try to build K, the linker will see two "versions" (copies) of the definition of f floating around in the application.

The fact that the two "versions" are exact copies of one another won't rescue you; the linker will still freak out on you, even though you could argue that it really doesn't need to, but not for some annoying rules of the language. The linker does not see that the original C++ definition of f exists only in one source code file (i.e. x.h), because that information does not get passed downstream from the preprocessor (and then further downstream by the compiler). All it knows is that two of the object files that are being fed in each contain a definition of f.

You might ask "But why doesn't the linker just look at the code in those two definitions and notice that they are the same?". That's a sensible question, but it's possible that the two translations of f (one in A, the other in B) are different, even though they behave the same. There is no reliable way for the linker to detect that the two translations of f behave the same way, so we don't ask it to do that. Instead, we let the linker give up.

allyourcode
Автор

This guy is great tutor and funny to watch.

la_ki
Автор

Hi CppCon, the slides for this presentation are still not available to my knowledge (I just searched in the GitHub repo and could not find them), which is a shame as the remaining examples are probably very interesting too. Thanks in advance!

(Great talk, by the way! Exactly what I needed right now, with a lot of information ❤)

DocteurZeuhl
Автор

Ben love your Back To Basics videos are superb !! I wish we were taught like this :)

muhammadharris
Автор

Linker scripts are a PITA. I usually have an idea of where RAM/Flash and abs addresses when i'm typing in the code source files. I don't want to write another obtuse file for linker obtuse statements. Some proprietary embedded compilers allows the "where" declarations in the source codes, so much better/cleaner.

leftunfounded
Автор

The slides of Ben Saks are not available on github. Is there any reason for that ?

Embedded_Republic
Автор

Where can I find the slides for this talk?

stormingbob
visit shbcf.ru