1

my Q is quite similar to these, but not exactly the same to:

Returning const reference to local variable from a function

Returning function-local variable as reference

I have a bit of code that is used to parse an xml file. what's basically happening is that a local variable is passed by reference OUT of the function using the return statement. To be more precise:

ezxml_t ezxml_parse_fd(int fd){

ezxml_root_t root;
//DO STUFF
return &root->xml;
}

the caller is the following

ezxml_t xml = ezxml_parse_fd(fd);

Well, the thing compiles and works (gcc)... but I have always known that a local variables are destroyed once their scope no longer exists... i'm confused

Community
  • 1
  • 1
nass
  • 1,453
  • 1
  • 23
  • 38

4 Answers4

2

The local variable is not "passed out by reference", because that would mean return &root;, which is not what your code says.

Rather, a pointer to some other, unrelated variable, which you didn't care to show us, is returned, and we should assume that the code was correctly written so that that pointer points to some dynamically allocated memory which will remain valid.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • ok the structure is as follows: `typedef struct ezxml_root *ezxml_root_t; struct ezxml_root { struct ezxml xml; ezxml_t cur; char *m; size_t len; char *u; char *s; char *e; char **ent; char ***attr; char ***pi; short standalone; char err[EZXML_ERRL]; };` and `typedef struct ezxml *ezxml_t; struct ezxml { char *name; char **attr; char *txt; size_t off; ezxml_t next; ezxml_t sibling; ezxml_t ordered; ezxml_t child; ezxml_t parent; short flags; };` – nass Sep 28 '11 at 12:02
  • basically `ezxml_parse_fd()` calls `ezxml_t ezxml_parse_str(char *s, size_t len)` to parse the xml string and that creates a `ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL);` now `ezxml_t ezxml_new(const char *name)` does a `ezxml_root_t root = (ezxml_root_t)memset(malloc(sizeof(struct ezxml_root)), '\0', sizeof(struct ezxml_root)); Finally, ezxml_new returns &root->xml back to ezxml_parse_str (stored in the local function's root var) and that in turn returns &root->xml up to ezxml_parse_fd.so in the end, the memory has been alloc deep inside a fn but it comes from the heap – nass Sep 28 '11 at 12:15
1

Once the function returns, function stack is unwound & references to function-local variables are invalid. You may get away with it for now, but don't rely on it!
Why not pass an output parameter to the function to store the value? Maybe, on these lines:

void ezxml_parse_fd(int fd, ezxml_t *parse_value) 
{

ezxml_root_t root;
//DO STUFF
*parse_value = &root->xml;
return;
}

...

ezxml_t xml;
ezxml_parse_fd(fd, &xml);

If you are using gcc there is a good chance that you might have seen a warning message "warning: function returns address of local variable" Please do pay attention to compiler warning! It is only trying to help you (most of the times) :)
Hope this helps!

another.anon.coward
  • 11,087
  • 1
  • 32
  • 38
  • i didn't write the code, im just checking it out and saw that. I've also been told that the code works (to parsing xml files at least). I wouldn't do it on my own code though – nass Sep 28 '11 at 11:56
0

yes, the local variables are destroyed already, but your reference points to the place in memory that hold last assigned value. The place where your variable was placed. And it will work in most cases in the single threaded environment for simple types. But when you allocate on the stack some object with destructor, the destructor will be called just when the execution of block (in your case -- function) will be finished. So outside the function you have a reference to destroyed object. Shortly: don't do this :-)

Jurlie
  • 1,014
  • 10
  • 27
0

In C - that is probably very wrong. Please tell us what ezxml_t is and what root->xml is.

My guess is that ezxml_t is automatically casted to by the pointer to root->xml that you return.

long404
  • 1,037
  • 9
  • 12