this is my first attempt to return a structure in C functions, and was confronted by strange problems.To be brief:the way gcc implements 'structure return' is a little hack. for example, if you write 'struct typenumber tn = parse_type(parser);', gcc will pass a ponter to 'tn'(the l-value) as the first argument when calling parse_type, although it's transparent to programmers, the 'parser' turned into the second argument anyhow.
when we disassemble the following code:
struct typenumber parse_type(strparser_t *parser){
parser->....
}
we will find within function body, the argument 'parser' is accessed using 'mov 0xc(%ebp),%eax', obviously gcc treats it as the second argument:
>>>>>>>>stack grow>>>>>>>>>>>>>>>>>>>>>
|parser| xxx | eip | ebp | ...
>>>>>>>>stack grow>>>>>>>>>>>>>>>>>>>>>
(xxx is a transparent pointer)
but this stack frame layout just came from gcc's view, because he saw the function returned 'struct typenumber' and he had promised himself every time he called a structure-returned function he would pass an additional pointer. only when he fulfiled the promise would the real layout be consistent with how he treated it. but sometimes he was not aware of being calling a structure-returned function.for example, we wrote in another source file:
parse_type(parser);
we compiled it without the protocol declaration of parse_type, so gcc regarded it as a impicit declaration which returned 'int'. now the tragedy happened, gcc only performed a common call:
lea `parser's address`, %eax
mov %eax, (%esp)
call parse_type
this caused a segment fault in my project.
I hope this article may help you.
share a bug:when you return a structure in C functions
Re: share a bug:when you return a structure in C functions
This is thoroughly well documented (and correct) behaviour.
John.
Regards,sysV i386 ABI wrote:If a function returns a structure or union, then the caller provides space for the return value and places its address on the stack as argument word zero. In effect, this address becomes a ‘‘hidden’’ first argument.
John.
Re: share a bug:when you return a structure in C functions
You must learn to always compile with all warning messages enabled so the compiler can inform you of real and potential problems in your code and thus help you find and fix bugs before you run your code. For gcc you should specify -Wall -Wextra -Werr -O2 and maybe some others. I'd also throw in -pedantic and -std=C99. The funny thing about the optimization level (i.e. -O2) is that when optimizations are disabled, some code analysis that's used to find problems and warn about them is disabled as well and so you want to use -O2. Also, the C99 mode does not allow K&R syntax and implicit int, the very thing you asked the compiler to do, treat a function without return type specified as returning int. C99 also requires function prototypes to be present. Help yourself and us, learn to use the compiler.
Re: share a bug:when you return a structure in C functions
Some calling conventions require the return value to be in EDX:EAX when a structure is small (div_t for example). Safest way is to explicitly declare the pointer: "void foo(struct bar *, ...)" instead of "struct bar foo(...)".
BTW This also teaches you to always correctly prototype your functions.
BTW This also teaches you to always correctly prototype your functions.