share a bug:when you return a structure in C functions

Programming, for all ages and all languages.
Post Reply
miaowei
Member
Member
Posts: 84
Joined: Wed Dec 18, 2013 9:10 am

share a bug:when you return a structure in C functions

Post by miaowei »

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.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: share a bug:when you return a structure in C functions

Post by jnc100 »

This is thoroughly well documented (and correct) behaviour.
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.
Regards,
John.
alexfru
Member
Member
Posts: 1111
Joined: Tue Mar 04, 2014 5:27 am

Re: share a bug:when you return a structure in C functions

Post by alexfru »

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.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: share a bug:when you return a structure in C functions

Post by qw »

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.
Post Reply