Returning structures from functions.

D

daniel

Hello ,


How safe is it to return a structure from a function.

Let's say we have the following situation:

typedef struct MyStruct{

int a;
char b;
} MyStruct;

MyStruct foo(void){
MyStruct s;

s.a = 2;
s.b = '1';
return s;
}

When function returns s , it must somehow make a "raw" copy of s? Is
this copy consistent.
I mean s.b will be '1' after foo call ?

Thanks,
Dan.
 
C

Chris McDonald

daniel said:
How safe is it to return a structure from a function.
Let's say we have the following situation:
typedef struct MyStruct{
int a;
char b;
} MyStruct;
MyStruct foo(void){
MyStruct s;
s.a = 2;
s.b = '1';
return s;
}
When function returns s , it must somehow make a "raw" copy of s? Is
this copy consistent.
I mean s.b will be '1' after foo call ?


What happens when you write a small range of programs, and test this.
Do you observe the behaviour that you expect, or something different?
 
R

Richard

Richard Heathfield said:
daniel said:
Hello ,


How safe is it to return a structure from a function.

Perfectly safe (all else being equal). See Section 6.2 of K&R2, first two
sentences.

The caveat is simply because it is possible for structures to contain
unsafe data. Consider:

struct foo { char *s; };
struct foo bar(void)
{
char t[] = "Baz";
struct foo quux;
quux.s = t; /* Danger, Will Robinson! */

return quux; /* Returning unusable pointer in quux - unsafe */
}

Yes, it's safe to return structs, in much the same way that it's safe to
carry small cardboard boxes around. But they just *might* contain
dynamite. (The trick is to be careful what you put in the box.)

Complete and utter scaremongering nonsense.

He could just as well have malloc'ed a struct and set the same field and
returned the pointer to a struct.

The standard data scoping applies regardless of whether a pointer to a
local or a pointer to a struct with a pointer to a local
 
J

James Kuyper

Richard said:
Richard Heathfield said:
daniel said:
Hello ,


How safe is it to return a structure from a function.
Perfectly safe (all else being equal). See Section 6.2 of K&R2, first two
sentences.

The caveat is simply because it is possible for structures to contain
unsafe data. Consider:

struct foo { char *s; };
struct foo bar(void)
{
char t[] = "Baz";
struct foo quux;
quux.s = t; /* Danger, Will Robinson! */

return quux; /* Returning unusable pointer in quux - unsafe */
}

Yes, it's safe to return structs, in much the same way that it's safe to
carry small cardboard boxes around. But they just *might* contain
dynamite. (The trick is to be careful what you put in the box.)

Complete and utter scaremongering nonsense.

He could just as well have malloc'ed a struct and set the same field and
returned the pointer to a struct.

Yes, it's also safe, in the analogous sense, to carry briefcases around,
but a briefcase might contain dynamite too. So?

How does saying "perfectly safe" constitute "scaremongering"? Where is
the "nonsense" in warning about the fact that while the return of the
value is safe, the value itself might be dangerous? The warning is
perfectly valid, and relevant. It's just a disguised version of the
problem in

char * bar(void)
{
char t[] = "Baz";
return t;
}

However, because it is a disguised version of that problem, it's a
harder one to spot.
 
N

Nick Keighley

daniel said:
How safe is it to return a structure from a function.

Perfectly safe (all else being equal). See Section 6.2 of K&R2, first two
sentences.

The caveat is simply because it is possible for structures to contain
unsafe data. Consider:

struct foo { char *s; };
struct foo bar(void)
{
  char t[] = "Baz";
  struct foo quux;
  quux.s = t; /* Danger, Will Robinson! */

  return quux; /* Returning unusable pointer in quux - unsafe */

}

Yes, it's safe to return structs,

and passing structs around by value can be expensive.
I once saw a function declared like this

void process_stats (struct Statistics);

when the programmer (probably) meant

void process_stats (struct Statistics*);

Since the stack was limited to 4K and struct Statistics was 11K
Bad Things happened.
 
R

Richard

Nick Keighley said:
daniel said:
How safe is it to return a structure from a function.

Perfectly safe (all else being equal). See Section 6.2 of K&R2, first two
sentences.

The caveat is simply because it is possible for structures to contain
unsafe data. Consider:

struct foo { char *s; };
struct foo bar(void)
{
  char t[] = "Baz";
  struct foo quux;
  quux.s = t; /* Danger, Will Robinson! */

  return quux; /* Returning unusable pointer in quux - unsafe */

}

Yes, it's safe to return structs,

and passing structs around by value can be expensive.
I once saw a function declared like this

void process_stats (struct Statistics);

when the programmer (probably) meant

void process_stats (struct Statistics*);

Since the stack was limited to 4K and struct Statistics was 11K
Bad Things happened.

A bug. It happens. Is there anything stopping the compiler passing a
pointer in real life anyway?

I am amazed that any system allowed this program to compile and link to
be honest. It knows the size of the struct after all. One would have
thought there would be safety features in the build system to try and
avoid such childish errors.
 
C

CBFalconer

Nick said:
.... snip ...

and passing structs around by value can be expensive.
I once saw a function declared like this

void process_stats (struct Statistics);

when the programmer (probably) meant

void process_stats (struct Statistics*);

Since the stack was limited to 4K and struct Statistics was 11K
Bad Things happened.

They would also have happened if declared as a local variable.
 
R

Richard

CBFalconer said:
They would also have happened if declared as a local variable.

You have repeated time and time again that stacks are "off
topic". Therefore it would be impossible for a "standards C programmer"
to consider such a beast when writing his code.

Which is it?
 
K

Keith Thompson

Richard said:
A bug. It happens. Is there anything stopping the compiler passing a
pointer in real life anyway?

Yes. If the function modifies its parameter, that change must not
affect the object that was passed as an argument.

The generated code *could* pass a pointer and then copy the structure
somewhere else, but on a system like the one described I can't think
of a good place to copy it.
I am amazed that any system allowed this program to compile and link to
be honest. It knows the size of the struct after all. One would have
thought there would be safety features in the build system to try and
avoid such childish errors.

You're assuming that the compiler is aware of the limited stack size
on the target system.
 
R

Richard

Keith Thompson said:
Yes. If the function modifies its parameter, that change must not
affect the object that was passed as an argument.

No. I said is there anything stopping the compiler passing an susing a
pointer. *Clearly* it can not do that if you pass the entire structure
and function modifies the contents for local usage. I didn't think I
would have to mention that.
The generated code *could* pass a pointer and then copy the structure
somewhere else, but on a system like the one described I can't think
of a good place to copy it.

What a stupid idea. Why would you want to do that? It totally defeats
the reason for passing a pointer.
You're assuming that the compiler is aware of the limited stack size
on the target system.

Actually I was assuming there it didn't. Which is why I was amazed.
 
K

Keith Thompson

Richard said:
What a stupid idea. Why would you want to do that? It totally defeats
the reason for passing a pointer.
[...]

Ask politely, and I might explain it to you.
 
F

Flash Gordon

Richard wrote, On 12/09/08 17:28:
No. I said is there anything stopping the compiler passing an susing a
pointer. *Clearly* it can not do that if you pass the entire structure
and function modifies the contents for local usage. I didn't think I
would have to mention that.

You asked for a reason, you got one. Another is that the function might
call another function which somehow modifies the original structure
(e.g. through a global pointer to one of its fields). There are
limitless possibilities for this kind of thing.

Actually I was assuming there it didn't. Which is why I was amazed.

In my experience with embedded systems it is quite common for the
compiler/linker to not do checks like this. The compiler generates code
to modify the stack pointer (or ar7, or whatever) with no knowledge of
the memory layout and the linker links with no knowledge of the stack
pointer modifications. Often you get to write the startup code in
assembler yourself if you want to, so unless the compiler/linker check
your startup code they know even less about how much space might be
available. On top of this, you might have a heap growing towards the
stack limiting space even further!
 
N

Nick Keighley

A bug. It happens.

yes. I was simply pointing out, to the OP, a possible problem
with passing structs by value. They have to be copied (usually).

Is there anything stopping the compiler passing a
pointer in real life anyway?

have you used an implementation that did this?

I am amazed that any system allowed this program to compile and link to
be honest.

really? Why?

It knows the size of the struct after all. One would have
thought there would be safety features in the build system to try and
avoid such childish errors

have you used an implementaion that does this by default?
Or are the checks extra code written into your build system?

This error is childish? Sometimes passing structs by
value is quite sensible.
 
R

Richard

Nick Keighley said:
yes. I was simply pointing out, to the OP, a possible problem
with passing structs by value. They have to be copied (usually).

Note your "usually": lets call it *A*
have you used an implementation that did this?

It was a question.

Now getting back to *A*, what did you mean if you were not clear on what
I eluded to?

I was merely pointing out that a clever compiler does not HAVE to pass
the structure if the called function does not update the struct in any
way.

really? Why?

Why do you think? It causes a crash that was avoidable by the tool set
looking at the numbers involved. Note I mentioned "system" in my
words. Indicating the toolset and target hw.
have you used an implementaion that does this by default?
Or are the checks extra code written into your build system?

This error is childish? Sometimes passing structs by
value is quite sensible.

Of course. No one said anything else. But not ones which exceed the
target stack that could be caught at build time. But then we are getting
into system specifics and Falconer will have a fit ....
 
D

David Thompson

How safe is it to return a structure from a function.

Let's say we have the following situation:

typedef struct MyStruct{
int a;
char b;
} MyStruct;

MyStruct foo(void){
MyStruct s;

s.a = 2;
s.b = '1';
return s;
}

When function returns s , it must somehow make a "raw" copy of s? Is
this copy consistent.

It returns the entire struct value, which is effectively a copy. (It
might not be implemented exactly that way, but that's the abstract
semantics, and thus what is implemented must 'appear' the same.)
I mean s.b will be '1' after foo call ?
s is a local variable and no longer exists after foo() returns.
But the .b field of _the returned value_ is '1', yes.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top