Live data from Hacker News

What happens before main() is executed in C and why is it important?

mymicrocontroller.com

31–40 of 104 posts

Re: What happens before main() is executed in C and why is it important?

#31

One other way to observe these steps a bit more clearly is to look at the startup code provided by a chip's manufacturer or generated by an IDE that targets the chip, such as Keil. Most will put this type of code in '.S' startup assembly files, which often also contain information like the memory addresses for hardware interrupts to use, and linker scripts for telling the compiler about the memory available on the ch…

It's not just "good practice", but instead the startup code is so specific to the platform that there really isn't "generic" startup code.

The generic compiler-provided startup code is fine for AVRs under most circumstances, since they're only produced by a single manufacturer and don't have fancy features like PLLs which need to be initialized. It's the more complicated chips where it gets a little hairy, especially if you have to deal with things like external RAM.

Re: What happens before main() is executed in C and why is it important?

#33
post #10

The linker script is what runs the global constructors in C++. Nothing preventing using a custom linker script in C to call some `premain()` function.

To be picky, the linker script lays out a sequence of calls to the global constructors so that the C runtime startup knows where to find and execute them.

Re: What happens before main() is executed in C and why is it important?

#34
post #31

Earlier quoted context omitted.

It's not just "good practice", but instead the startup code is so specific to the platform that there really isn't "generic" startup code.

The generic compiler-provided startup code is fine for AVRs under most circumstances, since they're only produced by a single manufacturer and don't have fancy features like PLLs which need to be initialized. It's the more complicated chips where it gets a little hairy, especially if you have to deal with things like external RAM.

I guess I rarely see the case for an AVR when you're not prototyping on an Arduino. You can get chips that are an order of magnitude more powerful per $/watt/and any other metric you'd want to use.

Re: What happens before main() is executed in C and why is it important?

#36

Earlier quoted context omitted.

In embedded you can usually modify every step from boot to main. They are just pieces of code you can interact with and make them do whatever you want and initialize stuff in whatever order you want, providing you know what you do. Deviating with a war story now, I once modified some startup code so it self-detected its boot location and initialized the ram data according to this location shift. It was fun, but debug…

What was the project for where you wrote code that self-detected its boot location?

Well, a bootloader and the self-detection was useful for the bootloader self-update. The update bootloader would be copied in a different section and on reset would start and copy itself over the original bootloader section.

I also wanted to maintain full functionality even at shifted location in case the self-copy process somehow failed. Never did fail, at least to my knowledge.

Re: What happens before main() is executed in C and why is it important?

#37

It should be noted that relying on static initialization as suggested in the article, while at times useful, can open a new set of problems until initialization order is well-defined (it's out of scope for the article, so I imagine the author is aware and just opting for brevity). Some compilers provide an explicit ordering mechanism (clang and GCC) and the there are proposals in the C++ standards at the moment, but…

> Depending on the architecture, there tends to also be well-defined hooks for functions to run pre and post-main which is another consistent model for initialization/shutdown.

Is atexit the post-main hook to which you were referring, or is that just the posix hook into a larger class of post-main hooks?

Re: What happens before main() is executed in C and why is it important?

#38
post #26

Earlier quoted context omitted.

Can you elaborate for those of us unfamiliar with topic?

Doing some of that kind of super low level code in a C++ static initialization constructor is almost certainly a poor choice. Like setting up memory and the stack pointer. Doing hardware init there can make a lot of sense, but you have to be careful from an architectural perspective.

The article is not advocating initializing the stack pointer with a C++ constructor.

Re: What happens before main() is executed in C and why is it important?

#39

Did someone on HN downvote everything except the bullet points in this article? Seriously-- why is the font greyed out? What possible purpose does this serve?

They have this in their stylesheet across the website

p{color:#999;line-height:1.4;margin-bottom:.75em}

so paragraph tags, sadly, have the ugly grey font color by default

Re: What happens before main() is executed in C and why is it important?

#40

Earlier quoted context omitted.

Doing some of that kind of super low level code in a C++ static initialization constructor is almost certainly a poor choice. Like setting up memory and the stack pointer. Doing hardware init there can make a lot of sense, but you have to be careful from an architectural perspective.

The article is not advocating initializing the stack pointer with a C++ constructor.

> * Memory segments are initialized. Memory segments such as .bss (for uninitialized data), .data (for initialized data such as static variables, global variables, local static variables, addresses of functions, and function pointers), and .text (where the actual code resides) are initialized and a valid stack is set up.

> * Command line arguments are received. This may not be relevant in embedded systems as in embedded systems we don’t usually call main() with arguments

> * The stack pointer is configured. This is necessary because the program needs to know where to start from. Note that some microcontrollers may require a start.c or cstart file that has the initialization code (whether this file is manually created or auto generated).

> Now that we know what happens before main(), we might wonder if there’s a way we can control what happens before main, or if there is a way we can write our own version of what happens before main(). In C, the answer is largely no. Whatever happens before main() is largely dependent on your architecture and compiler. However this is in fact possible in C++.

> One way you can do this in C++ is by declaring a global class object. Since global variables are initialized before main(), the constructor of the class you have initialized as global will run before main(). You can therefore place the code you want to run before main() in such a constructor.

Certainly looks like it is.

Post reply on HN