开发者

Why main() in C++ cannot be inlined?

开发者 https://www.devze.com 2023-03-26 22:31 出处:网络
开发者_JS百科I was reading the C++ FAQs and I noticed one sentence. main() cannot be inline. Why is this?In C++ it is not legal to call the main function in your code, so there\'d be no way it co
开发者_JS百科

I was reading the C++ FAQs and I noticed one sentence.

main() cannot be inline.

Why is this?


In C++ it is not legal to call the main function in your code, so there'd be no way it could ever be inlined.


Because the standard says so:

[2003: 3.6.1/3]: The function main shall not be used (3.2) within a program. The linkage (3.5) of main is implementation-defined. A program that declares main to be inline or static is ill-formed. The name main is not otherwise reserved. [Example: member functions, classes, and enumerations can be called main, as can entities in other namespaces. ]

And why does it say so? Because it's trying to leave as much about the implementation of main to the individual .. well, implementation .. as is possible, and doesn't want to limit implementations by requiring that inline be valid here when it arguably has no practical benefit.


My friend on the committee confirmed this:

There's no reason why an inline main() wouldn't work, per se. [..] I could have a C++ interpreter that can invoke inlined main(). [..] [But] inline/static main() are forbidden in order to hopefully avoid confusion. I find it hard to imagine that the rationale would be anything additional to what's already been said in [this Q&A].


BTW, don't confuse the inline hint keyword with actually inlining functions. You can mark a function inline and it may not be physically inlined.

So, even if it were true that main "cannot be inlined" (and strictly speaking it is not true, though inlining main would be rather awkward and pointless as explained in other answers), it could theoretically still support the inline hint keyword just fine.

It doesn't for the reason stated above, and in litb's answer: it would complicate matters for no real benefit.


The C runtime library needs to find this symbol in order to "know" which function to run.


You cannot directly call main() (it's forbidden in c++), so there is no point of inlining it.


Usually main() is called from systems init() function. Thus, it is needed that there can be exactly one definition for main().

Now, if we can inline the main() function and include in a header file then, for every translation unit there will be different definition for main(). Which is not allowed. You can declare main() in a namespace and inline it. But not the global main().


firstly you must understand how work function with inline

example:

 inline void f() {
     int a  = 3;
     a += 3;
     cout << a;
 }

 int main() {
      f();
      return 0;
 }

will look like to the compiler as:

 int main() {
        int a  = 3;
        a += 3;
        cout << a;
        return 0;
 }

looking at this example, how do you want to make main inline? This method is inline immediately.


The C++ standard says that the main function cannot be inlined, per @Tomalak Geret'kal's reply. This response discusses possibility of inlining of the main function, were the restriction in the Standard removed.

Definition of Inline
The inline keyword is a suggestion to the compiler to paste the contents of the function in-situ. One intent is to remove the overhead present in calling and returning from a function (subroutine).

An important situation of inlining is the case where there is a pointer to the function. In this case, there must be at least one static copy of the function. In this case, the linker can resolve "external linkages" of the inlined function because there is one static version.

Important to note that the compiler and linker determine whether or not to paste the contents or calls a single instance of the function.

Also of note, functions that are not tagged by the programmer may also be inlined by the compiler.

Inlining the main function
Since there is only one invocation of main allowed, how it is linked is up to the compiler. Single instances of inline functions are allowed by the Standard. The compiler is allowed to convert an inlined function into a function call to a single instance. So the compiler would ignore an inline suggestion for the main function.

The compiler and linker would have to insure that only one instance of the inlined main function exists. This where the tricky part comes in, especially with external linkage. One process for ensuring one instance is to leave information that a translation has a 'main' function whether or not it is inlined. Note: When a call to an inline function is made, the compiler is allowed to remove the function from the symbol tables for external linkage, since the idea is that the function won't be called by external functions.

Summary
Technically, there is nothing preventing the main function from being inlined. The machinery already exists for converting inlined functions into single instances and for identifying multiple instances of a function. When there is a pointer to an inlined function, a single instance of a function is made, so it has an address. This machinery would satisfy the Run-Time Library requirements for main having an address. In the case of inline for the main function, it would be ignored but there should not be any reason to prevent this syntax (except confusing people). After all, there are already syntax cases that are redundant, such as declaring a parameter that is passed by value (copy) as const.

"That's just my opinion, I could be wrong." -- Dennis Miller, comedian.


Others have remarked that an invocation of main can not meaningfully be inlined at the machine code level. That's rubbish. It would require a bit of help from the linker (like global optimization) or else per-application recompilation of a bit of the runtime library, but it's quite doable, no technical problem here.

However, the hinting effect of inline, that calls should preferably be inlined, is irrelevant for a function that is only called once and at the top level of control, as main is.

The only guaranteed effect of inline is to allow an external linkage function to be defined (identically) in two or more translation units, i.e. affecting the One Definition Rule.

As a practical matter this allows the definition to be placed in a header file, and placing it in a header file is a also practically necessary to guarantee identical definitions.

That does not make sense for main, so there is no reason for main to be inline.


You can only define main once. So putting inline would not serve any purpose - inline only has a significant purpose on functions you can define multiple times in a program (all definitions will be treated as if there were only one definition and all definitions are required to be the same).

Because inline functions can be defined multiple times in a program, and inline also serves the purpose of making calls to an inline-marked function as fast as possible, the Standard requires inline functions to be defined in every translation unit in which it is used. So compilers will usually throw away the definition of a function if it is inline and the function wasn't used by the code in the current translation unit. To do that for main would be entirely wrong, which goes to show that inline and the semantics main has is entirely incompatible.

Note that the question in your title "Why main() in C++ cannot be inlined?" and the statement you quote out of the Standard concern different things. You are asking whether the function can be inlined, which commonly is understood to insert the code of a called function completely or partially into the calling function. Just marking a function inline doesn't imply inlining that function at all. It's entirely the compiler's decision, and of course if you never call main (and you cannot do so) then there is nothing to be inlined.


If you linked statically to the CRT and enabled some link-time compilation-inlining (like MSVC has) it might be possible to inline it.

But it doesn't really make sense. It will be called once and that function call-overhead is practically naught compared to everything else that is done before the first line in main executes.

...

Aaand, it is an easy way to force the symbol to appear only once in your executable. :)


There are a number of basic reasons. Basically, main is called from the basic initialization routine of the runtime, and only from there. That code was (obviously) compiled without knowing that your main was inlined. Modern compiler technology is capable of inlining across module boundaries, but it's an advanced feature, not supported by many older compilers. And of course, the benefits of inlining are only present when a function is called very frequently; by definition, main will be called exactly once, no more, no less.


I see the standard says so, but the real practical answer would be as simple as stating that the runtime added to every C and C++ program has to call to some point in the executable. That function should have an external symbol (and address when running) so that the linker can find it to be called at the beginning of execution. Hence you cannot declare it as inline, because inlined the compiler wouldn't generate an external symbol for it.


Since its the main() function, which starts the execution, when the code gets compiled to binary, everything is in the main() itself. so you can say, it already inlined!

And yes, its illegal to use inline for your C++ program, that's more about a syntax!


For most combinations of compiler/archetecture, the main() function in the source becomes a reasonably normal function in the final binary. This is only because it's convenient on those archetectures, not because the standard says it must be so.

On memory constrained archetectures, many compilers, ones which produce a flat binary (like intex hex format) instead of a dynamic linker friendly container (like elf or xcoff), optimize all of the boilerplate away, since it would just be bloat. Some architectures don't support function calls at all (only a limited subset of C++ is possible on these platforms.)

In order to support the widest variety of such architectures and build environments, the standard elects keep the semantics of main() as open as possible, so that the compiler can do what's right for the widest variety of platforms. That means that many features available in the language as a whole cannot apply to the startup and shutdown of the application itself.

If you need something like an inline main() (or reentrancy, or any fancy feature) you can of course call the main function something else:

inline int myMain(int argc, char **argv) { /* whatever */ }
int main(int argc, char **argv) { return myMain(argc, argv); }


Inline functions are having static scope by-default. It means if we declare main() as inline, it's scope will be limited to the file where it is defined. Yet, the C start-up library (provided by compiler vendor) needs 'main' to be a global symbol. There are some compilers that allow to modify entry point function (e.g. main) using linker flags.


inline functions don't usually have an address, so there is no portable way to call main, main() needs an address on which the init code can jump into. Inlined functions are meant to be stuck into the calling function, if main is inlined, it should be inlined into the init code of the program, which is not portable either.


operating system loads binary data to memory; looks for entry point (the 'main' symbol in c/c++); makes far jump to the addres of the entry point label. Operating system does not know anything about main function in your code until the program is not loaded.

0

精彩评论

暂无评论...
验证码 换一张
取 消