Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
395 views
in Technique[技术] by (71.8m points)

c - When main is defined without parameters, will argc and argv still be present on the stack?

Consider the very simple:

int main(void) {
    return 0;
}

I compiled it (with mingw32-gcc) and executed it as main.exe foo bar.

Now, I had expected some sort of crash or error caused by a main function explicitly declared as being bereft of life parameters. The lack of errors led to this question, which is really four questions.

  • Why does this work? Answer: Because the standard says so!

  • Are the input parameters just ignored or is the stack prepared with argc & argv silently? Answer: In this particular case, the stack is prepared.

  • How do I verify the above? Answer: See rascher's answer.

  • Is this platform dependant? Answer: Yes, and no.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I don't know the cross-platform answer to your question. But this made me curious. So what do we do? Look at the stack!

For the first iteration:

test.c

int main(void) {
   return 0;
}

test2.c

int main(int argc, char *argv[]) {
   return 0;
}

And now look at the assembly output:

$ gcc -S -o test.s test.c 
$ cat test.s 
        .file   "test.c"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        movl    $0, %eax
        popl    %ebp
        ret
        .size   main, .-main
        .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
        .section        .note.GNU-stack,"",@progbits

Nothing exciting here. Except for one thing: both C programs have the same assembly output!

This basically makes sense; we never really have to push/pop anything off of the stack for main(), since it's the first thing on the call stack.

So then I wrote this program:

int main(int argc, char *argv[]) {
   return argc;
}

And its asm:

main:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        popl    %ebp
        ret

This tells us that "argc" is located at 8(%ebp)

So now for two more C programs:

int main(int argc, char *argv[]) {
__asm__("movl    8(%ebp), %eax
"
        "popl    %ebp
"
        "ret");
        /*return argc;*/
}


int main(void) {
__asm__("movl    8(%ebp), %eax
"
        "popl    %ebp
"
        "ret");
        /*return argc;*/
}

We've stolen the "return argc" code from above and pasted it into the asm of these two programs. When we compile and run these, and then invoke echo $? (which echos the return value of the previous process) we get the "right" answer. So when I run "./test a b c d" then $? gives me "5" for both programs - even though only one has argc/argv defined. This tells me that, on my platform, argc is for sure placed on the stack. I'd bet that a similar test would confirm this for argv.

Try this on Windows!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...