Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C (http://www.programmingforums.org/forum60.html)
-   -   Function returning double pointer ? (http://www.programmingforums.org/showthread.php?t=14718)

xavier Dec 9th, 2007 12:57 PM

Function returning double pointer ?
 
:

  1. int * add(int x,int y)
  2. {
  3. int z;
  4. z = x+y;
  5. return(&z);
  6. }


Ok, that works. How about when i have something like :

char ** thing(){
return (???);
}

and : char *(??) = thing().

How exactly should it look ?

I'm quite sure this is a no brainer .. but .. :'(
Help.

Jessehk Dec 9th, 2007 3:05 PM

Re: Function returning double pointer ?
 
In your first snippet, z is local to the function add(). What your doing is returning the address of a variable that doesn't exist outside the function -- it's an error.

In your second example, If thing() returned a pointer to memory on the heap (allocated by malloc()), then to return it, you'd just return the pointer from the function -- there's no need to return a pointer to a pointer to a char (char **).

If I've made any errors, any of the numerous C-gods present will hopefully correct them.

EDIT: I ran his code involving add() and although valgrind reports an error, the correct answer is computed. I'm 99.99% sure that it is wrong. Why is 5 being computed at all?

:

  1. #include <stdio.h>
  2.  
  3. int *add( int x, int y ) {
  4.     int z = x + y;
  5.  
  6.     return &z;
  7. }
  8.  
  9. int main() {
  10.     int *ans = add( 2, 3 );
  11.     printf( "%d\n", *ans );
  12.  
  13.     return 0;
  14. }


:

==7676== Memcheck, a memory error detector.
==7676== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==7676== Using LibVEX rev 1732, a library for dynamic binary translation.
==7676== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==7676== Using valgrind-3.2.3-Debian, a dynamic binary instrumentation framework.
==7676== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==7676== For more details, rerun with: -v
==7676==
==7676== Invalid read of size 4
==7676==    at 0x80483B3: main (in /home/jesse/example)
==7676==  Address 0xBEB40904 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
5
==7676==
==7676== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 1)
==7676== malloc/free: in use at exit: 0 bytes in 0 blocks.
==7676== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==7676== For counts of detected errors, rerun with: -v
==7676== All heap blocks were freed -- no leaks are possible.


Dameon Dec 9th, 2007 3:34 PM

Re: Function returning double pointer ?
 
Yes, the code is wrong, valgrind is right. As usual ;)

When you make a function call, the stack pointer will be adjusted by some number of bytes.
This effectively reserves space on the stack for local variables, the return address, parameters, etc.

The integer z is a local variable, so it's located on the stack. Probably somewhere around the address to return to, etc. &z gives the address of z as you expect.

When add() returns, the stack pointer is changed back to where it was before add() was called. The local variables, etc are still there. You can still access that address and get the correct answer. However, the next time you call a function, z will get overwritten by something else, because its parameters and local variables may occupy the same space. It works right now, but will surely break later.

Jessehk Dec 9th, 2007 4:03 PM

Re: Function returning double pointer ?
 
Thanks for the explanation Dameon.

I realized that I didn't write a correct definition for int main( void ). I will make a sacrificial offering to the C gods when time permits.

grumpy Dec 9th, 2007 6:58 PM

Re: Function returning double pointer ?
 
Quote:

Originally Posted by Jessehk (Post 138250)
Thanks for the explanation Dameon.

Dameon told some minor fibs. His explanation is just one of many possibilities for what happens. The formal result of the code is undefined: any set of observable or unobservable effects are allowed to happen.
Quote:

Originally Posted by Jessehk (Post 138250)
I realized that I didn't write a correct definition for int main( void ). I will make a sacrificial offering to the C gods when time permits.

Definitions of main() as "int main()" and "int main(void)" are equivalent. Even the latest C standard uses both forms on occasion.

Interestingly enough declarations (eg function prototypes) of such functions are different: the first form declares a function that takes an unspecified set of arguments, and the second declares a function that takes no arguments.

This is one of the minor anomalies introduced into the latest C standard: and some of the reasons are, I suspect, non-technical. The "gods of C" have not earned any sacrificial offerings with this one.

xavier Dec 9th, 2007 11:12 PM

Re: Function returning double pointer ?
 
ok, thanks for the replies .
I didn't really check that code, int * .. I was using it as an example for a function returning a pointer.

the

char ** thing(){
return (???);
}

and : char *(??) = thing().

is actually a function generated by rpc. So I'm stuck with it. The problem is that i don't know how to return the value, and how to use the function in another part of the program.

grumpy Dec 10th, 2007 4:42 AM

Re: Function returning double pointer ?
 
You'll have to be a bit more precise. What is the caller expecting to receive when thing() returns?

And don't tell me a char **. I mean what operations does it expect to do with that pointer, and what does it expect the pointer to point at?

xavier Dec 10th, 2007 4:55 AM

Re: Function returning double pointer ?
 
This is the original :
Server :
:

  1. static double found;
  2. double * average_1(input_data *input,CLIENT *client)
  3. {
  4.   found = 1;
  5.   return (&found);
  6. }
  7.  
  8. double * average_1_svc(input_data *input,struct svc_req *svc)
  9. {
  10.   CLIENT *client;
  11.   return(average_1(input,client));
  12. }


average_1_svc will returne to the client;

Client:
:

  1. double  *result_1;
  2. result_1 = average_1(&average_1_arg.input_data, clnt);
  3. printf("%e\n",*result_1);



Now I modified the rpc .x file to return a string. In turn it generated functions like:
:

  1. char ** average_1(input_data *input,CLIENT *client) {
  2. }


The problem is that in the function i don't know how to return a string
like :

char * string = malloc(sizeof(char)*100);
return string;

and if i return it ... how do I use the function on the client side?

grumpy Dec 10th, 2007 6:51 AM

Re: Function returning double pointer ?
 
So much for a question being asked in a clear form. :icon_rolleyes:

Quote:

Originally Posted by xavier (Post 138268)
This is the original :
Server :
c Syntax (Toggle Plain Text)
  1. static double found;
  2. double * average_1(input_data *input,CLIENT *client)
  3. {
  4. found = 1;
  5. return (&found);
  6. }
  7. double * average_1_svc(input_data *input,struct svc_req *svc)
  8. {
  9. CLIENT *client;
  10. return(average_1(input,client));
  11. }
static double found; double * average_1(input_data *input,CLIENT *client) { found = 1; return (&found); } double * average_1_svc(input_data *input,struct svc_req *svc) { CLIENT *client; return(average_1(input,client)); }

Well, as described previously, anything the caller does with these functions will yield undefined behaviour. A local variable is not guaranteed to exist when a function returns, so returning it's address gives a pointer to something (potentially) non-existent. If the caller dereferences (eg writes to or reads from) that address, the net result is undefined behaviour.

Quote:

Originally Posted by xavier (Post 138268)
c Syntax (Toggle Plain Text)
  1. char ** average_1(input_data *input,CLIENT *client) {
  2. }
char ** average_1(input_data *input,CLIENT *client) { }

The problem is that in the function i don't know how to return a string
like :

char * string = malloc(sizeof(char)*100);
return string;

and if i return it ... how do I use the function on the client side?

You don't need a function to return a pointer to a pointer if you simply want to give the caller a string.

For example;
:

#include <stdio.h>
#include <stdlib.h>

char *function()
{
    char *x = malloc(100);
    strcpy(x, "Hello");
    return x;
}

int main()
{
    char *str = function();
    fprintf(stdout, "%s\n", str);
    free(str);    /* necessary to release the data malloc()'ed by function */
}

The reason this works is that function() returns the value of x, not it's address. That value is the address of memory that has been obtained using malloc(), which is guaranteed to exist until the corresponding call of free().

However, if you change function to;
:

char *function()  /*  This function makes the caller exhibit undefined behaviour */
{
    char a[100];
    strcpy(a, "Hello");
    return a;
}

the caller will exhibit undefined behaviour because the array a does not exist when the function returns. And the return statement returns the address of the first element in a. But a will no longer exist when the function returns.....

xavier Dec 10th, 2007 9:32 AM

Re: Function returning double pointer ?
 
Ok, the method signatures are generated with rpcgen. So i'm not modifying them.
Now , it's all interesting and stuff , and I do appreciate you taking the time to answer Grumpy.

But the question is quite simple . How can I work with " char ** " method signatures ?


All times are GMT -5. The time now is 3:49 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC