GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 05-Mar-2004, 13:36
elumira elumira is offline
New Member
 
Join Date: Mar 2004
Posts: 2
elumira is on a distinguished road

Passing Pointers To Pointers in Functions


Hi, I'm having a great deal of problem trying to access the contents of a char** that was malloc'ed and set within a function. Here's an example code:

CPP / C++ / C Code:
int mytest(char **msg) {

   msg = (char **) malloc (sizeof(char *));
   msg[0] = (char *) malloc (sizeof(char)*100);

   strcpy(msg[0],"Hello There");

   printf("1msg=%s\n",msg[0]);
   return 1;
}

int main() {

   int result;
   char **msg;

   result = mytest(msg);

   printf("2msg=%s\n",msg[0]);

   return 0;
}

In the first print (before the mytest function exits) I'm able to print "Hello THere". However, in the main program I seem to be getting nothing in msg[0] anymore. It seems like once I exitted the function (mytest), the msg variable has been deallocated or loses it's pointer to the allocated memory.
Please help...
Thanks
Last edited by dsmith : 05-Mar-2004 at 13:42. Reason: Use [c] and [/c] to add C syntax highlighing
  #2  
Old 05-Mar-2004, 13:48
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Hello Elumira. Welcome to GIDForums. This is going to sound weird, but you actually need to pass a pointer to the msg double pointer. Otherwise you are just passing a copy of it and the changes are not made to the original. Your code would look more like:

CPP / C++ / C Code:
int mytest(char ***msg) {

   *msg = (char **) malloc (sizeof(char *));
   *msg[0] = (char *) malloc (sizeof(char)*100);

   strcpy(*msg[0],"Hello There");

   printf("1msg=%s\n",*msg[0]);
   return 1;
}

int main() {

   int result;
   char **msg;

   result = mytest(&msg);

   printf("2msg=%s\n",msg[0]);

   return 0;
}

Which is just awful IMO. Can you change your function to return the msg double pointer instead of result? Or have result come back through a reference variable, ie:

CPP / C++ / C Code:
char** mytest(int* result) {

   char** msg;

   msg = (char **) malloc (sizeof(char *));
   msg[0] = (char *) malloc (sizeof(char)*100);

   strcpy(msg[0],"Hello There");

   printf("1msg=%s\n",*msg[0]);
   *result = 1;
   return(msg);
}

int main() {

   int result;
   char **msg;

   msg = mytest(&result);

   printf("2msg=%s\n",msg[0]);

   return 0;
}

I like this better, because the indirection doesn't get as confusing.

HTH
  #3  
Old 05-Mar-2004, 14:15
elumira elumira is offline
New Member
 
Join Date: Mar 2004
Posts: 2
elumira is on a distinguished road
No, the function prototype is actually for a char**. And we have to use that. So is there no way to pass it as a reference from main using char**? Thanks for the assistance.
  #4  
Old 05-Mar-2004, 14:24
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by elumira
No, the function prototype is actually for a char**. And we have to use that. So is there no way to pass it as a reference from main using char**? Thanks for the assistance.

Yes and no. The first example that I gave does just that. When you are talking about a reference in C, it is simply passing an address of that variable to the function. Take the easier to understand function where we pass the &result. If we were to pass result only, it would make a new variable local to that function and put the value of result in it. When your function exits, the memory of that variable is destroyed and the value is lost.

On the other hand, if I pass the address of the variable, as in &result, the function accepts this as a pointer to the variable declared in main. Therefore, any work or changes done on that are done to the actual variable.

So in other words, when I pass the &msg, I am passing up the memory location of where msg is stored at. Anything I do to that in the function is being done through a pointer to update the passed variable.

If you pass only msg, it is making a copy of that msg for the local function and deleting it upon exit.

When you say the function prototype is char**, what exactly do you mean?
  #5  
Old 05-Mar-2004, 14:48
aaroncohn's Avatar
aaroncohn aaroncohn is offline
Regular Member
 
Join Date: Feb 2004
Location: Bay Area, CA.
Posts: 564
aaroncohn is a jewel in the roughaaroncohn is a jewel in the roughaaroncohn is a jewel in the rough
I believe he was referring to the return value and just used the wrong terminology.
  #6  
Old 05-Mar-2004, 15:34
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by aaroncohn
I believe he was referring to the return value and just used the wrong terminology.

If that is the case, then obviously the second example is perfect.

But I think he is prototyping a function that is supposed to be:

CPP / C++ / C Code:
int mytest(char** msg);

and if so, I suspect what he really wants is to pass only one string, like so:

CPP / C++ / C Code:
int mytest(char **msg) {

   *msg = (char *) malloc (sizeof(char)*100);

   strcpy(*msg[0],"Hello There");

   printf("1msg=%s\n",*msg[0]);
   return 1;
}

int main() {

   int result;
   char **msg = (char**) malloc(sizeof(char**)*MAX);
   int x = 0;

   result = mytest(&msg[x]);   //Where X would be indexed for each added array.

   printf("2msg=%s\n",msg[0]);

   return 0;
}

But, I am just stabbing in the dark now. If elimura posts back, maybe he can give us some insight....
  #7  
Old 05-Mar-2004, 15:47
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,234
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all
A couple other points.
Casting the return of malloc() is not necessary. This link explains why:
http://faq.cprogramming.com/cgi-bin/...&id=1043284351
But kowing schools, they tend to use late 80's early 90's software so it may in fact be a factor.

Every buffer you allocate must be free()'d. See this link:
http://www.eskimo.com/~scs/C-faq/q7.22.html
Since the buffer was allocated during runtime, when the program ends, that buffer cannot be deallocated by the system -- it doesn't really know the buffer exists. The program is not good at adding to it's "things to do" list while running.
  #8  
Old 05-Mar-2004, 17:15
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by WaltP
A couple other points.
Casting the return of malloc() is not necessary.
Wow. Way to show how long it has been since I took a C class Walt! That is great information. I am really interested in the part about it not being a problem unless stdlib is not included. This definitely calls for a reinvestigation of my code. Excellent source. Thank you.

Quote:
Every buffer you allocate must be free()'d.
This is just good programming practice, period. It is sloppy programming not to do it and it should always be done. That being said, it doesn't specifically state that the program will not clean up upon exit, but it is probably a good idea to clean up after yourself anyway. It makes you wonder if the "memory drift" problem that is often apparent in windows is not caused by applications not cleaning up properly.

This is all great information. Thank you Walt.
  #9  
Old 05-Mar-2004, 21:23
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,234
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all
Quote:
Originally Posted by dsmith
Wow. Way to show how long it has been since I took a C class Walt! That is great information. I am really interested in the part about it not being a problem unless stdlib is not included. This definitely calls for a reinvestigation of my code. Excellent source. Thank you.
Yes, the information on that site is quite good. I haven't check the tutorials (I hear they tend to be iostream.h vintage) but the FAQ is well worth checking.

Quote:
Originally Posted by dsmith
This is just good programming practice, period. It is sloppy programming not to do it and it should always be done. That being said, it doesn't specifically state that the program will not clean up upon exit, but it is probably a good idea to clean up after yourself anyway. It makes you wonder if the "memory drift" problem that is often apparent in windows is not caused by applications not cleaning up properly.
My assumtion is that if you don't free the memory allocated, you have a leak. Period.

Let's assume upon exiting, the memory is freed, what would have to happen during malloc.
1) malloc() would have store the address and size of any and all allocated memory in it's own internal "allocation table"
2) realloc() would have to modify this table.
3) free() would have to modify this table
4) upon exit, the system would have to realize this table exists and start freeing all this memory.
Based solely on #1, I'll bet this is far too complex for most if not all systems. It would have to be written into the OS as well as the compiler. I don't see this as something that is actually being done. If it was,
1) why are there so many programs written to look for memory leaks?
2) why do they so adamantly state "always free your allocated buffers?"

2 more dracmas
 
 

Recent GIDBlogLast Week of IA Training by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 06:47.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.