main() never executing. an academic exercise

Frequently I have heard the question, "Can you write a program without main()?" The answer is yes... if you either delve into assembler or do some command line options to the compiler to redefine the start point and such. Well, as an academic exercise, I wrote the following code. It executes any code you like without ever executing main(). You can use the program's arguments because they're global and you can reliably return a value. The following code is tested and works. This therefore is a fully working program. You can run whatever code you like inside it, return a value for the program, and take command line arguments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <cstdlib>
#include <cstdio>
#include <iostream>

using namespace std;

int before_main(void);

int the_actual_program(void);

 /* we need a wrapper function to set it's output to something. if we don't,
    we can't let the program have a return value. the reason why is we have to 
    call exit() as part of a function to give this a return value AND bypass
    main(). exit needs to be called with the program's return value. we need
    to assign a global value by a function's return value... that function will
    execute before main(). this function executes another functions that IS the
    actual program bypassing it's own return statement. it never returns, but it
    IS called and executes. and that's our goal.
     */
int before_main(void)
{
    exit(the_actual_program());
    return 0; // this never actually runs. it's here so we can assign before_main()'s value to something
}

int foo_bar = before_main(); // here we make a global assignment which must occur before main()

int main(int argc, char *argv[])
{
    puts("We're inside of Main()"); // this never runs.
    getchar(); // this is a pause so tha twhen you run the program, it'll be proven this enver pops up.
    return foo_bar; // we put this here so the compiler doesn't complain we never use it.
}

int the_actual_program(void)
{
    puts("We're NOT inside of Main()"); // this WILL run
    getchar(); // a pause.
    
    return 0; // yes, this is the program's return value due to exit() in the wrapper function
}


Nota Bene: I know I posted this in another part of the forum by me. There is simply more than one place where it is appropriate. It'll simply get more eyes this way, perhaps answer more questions as well.

Also, the only use I can conceive of this is HOPING that the inline assembler sets the code before main() with higher authority during pre main() assignments and this would allow the programmer to do things s/he otherwise couldn't or that would result in quick segfaults.
Last edited on
I have two questions:
1. Why would you ever want to do this?
2. What order are globals initialized in? IINM, the order is undefined, which means that as long as before_main() hasn't returned, you can't use any globals (presumably including std::cout), so that's another reason not to do this.
Last edited on
Pointless nonsense.
Srsly, wtf is this for anyway? I can write a program without main:

1
2
3
4
5
6
7
8
#define ! m
#define @ a
#define % i
#define _ n

int !@%_() {
    //no main included!
}
firedraco :

On which compiler does this compile?
Not on GCC
Uh...my head? <_<;
Uh...my head? <_<;

:D, Where can I download that? Seems like it has lots of powerful features.
^I think everyone comes with it installed by default.
Can you write a program without main()?


The answer should be no! Although you might be able to write a hack that causes main to not execute, you can't really write a program without writing the main function. No offense but where do you hear or see people frequently asking this question? I've never seen or heard this question asked before.
It was a bit of boredom. Like I noted in there, the only possible use I can think of is the fact that the inline assembler file is assembled into the program after linking has segments and permission levels set up. Or rather, certain inline assembler instructions can only have a certain level of authority when the operating system sets it to be so to prevent a program from doing things like screwing up the OS's stack. This also has something to do with segmenting. I've yet to look at the assembler output though. This might cause the code to be in a different segment because it's run outside of main() to set things up. This would allow you to, possibly, if this convoluted idea works, peak at things in memory and such that you couldnt' otherwise due to segmentation. As an example. Finally, yeah, this really IS nonsense. But it's sublime hilarious nonsense that I did because I was bored.

Oh, and there ARE ways to write code TRULY without main(). The actual internnal function that sets everything up... you'd have to reimplement that. OR write it partially as an inline assembler program and cause the inline assembler, that doesn't have a main(), to call a funciton in your code and such. How else do you think they do it in OS's? Also, there's a GCC compiler optino that changes the program start point. RTFM in response to that. FINALLY, I ran this on wxDev-C++. I do beleive it uses MinGW.
Last edited on
But it's sublime hilarious nonsense that I did because I was bored.
Next time, try doing something that's actually useful.

Also, there's a GCC compiler optino that changes the program start point.
Yeah, that's totally not the same as main().

the only possible use I can think of is the fact that the inline assembler file is assembled into the program after linking has segments and permission levels set up. Or rather, certain inline assembler instructions can only have a certain level of authority when the operating system sets it to be so to prevent a program from doing things like screwing up the OS's stack. This also has something to do with segmenting. I've yet to look at the assembler output though. This might cause the code to be in a different segment because it's run outside of main() to set things up. This would allow you to, possibly, if this convoluted idea works, peak at things in memory and such that you couldnt' otherwise due to segmentation.


No, I can guarantee that that is not the case. The kernel executes all code as a user-level process, not just the
code that runs after main() is called.
Also, the segmentation of your program is not related to how your code looks. Executable code always goes into the 'text' segment. Read-only data into the 'data' segment. Etc.
Yes there is a way to write a program without main()... how do you suggest operating systems are coded? With a main()? Well... what would call main()? There is no main() in the linux kernel. And don't tell me none of you haven't done something useless because you were bored to see if it could be done.
You are confusing layers of abstraction.

Everything has an entry point -- even the OS.

The C and C++ languages define that entry point as int main() or int main( int argc, char** argv ).

And for the record, I never indicated that this thread was stupid or pointless, or that I disapproved of either it or you.
Topic archived. No new replies allowed.