LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 08-14-2010, 11:23 AM   #1
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 547

Rep: Reputation: 38
return char* from func in c?


Hi,

I wrote a function that needs to return a string created in the function in c.

Is it the best way in c to have a return pointer as an argument? Using malloc makes it hard to know when to free etc and using an internal static memory allocation will get erased leaving the function i suppose. Having global pointers just suck. I cant think about other options.

like this

char * my_func(char* ret)
{
strcpy(ret, some_get_a_string_func()); /* assigne the sting pointer */
return ret;
}


a lot of other languages do not have these problems. So im not so used to it.

Thanks
 
Old 08-14-2010, 11:54 AM   #2
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by kalleanka View Post
Is it the best way in c to have a return pointer as an argument?
That is a common solution: Make the caller responsible for allocating and owning the memory.

Quote:
Using malloc makes it hard to know when to free
That is the only really general method in C and you are correct that knowing when to free is one of the difficult aspects of C.

Quote:
using an internal static memory allocation will get erased leaving the function
No. An internal non static memory allocation might get reused at any time starting when you leave the function. But an internal static memory allocation is safe until you call the function again. If you will design so the caller will be done with one result before calling the function for another and you know a reliable but reasonable max size, then internal static memory allocation is a common good answer for your problem.
 
Old 08-14-2010, 12:08 PM   #3
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 547

Original Poster
Rep: Reputation: 38
Thanks.

Quote:
Originally Posted by kalleanka View Post
Hi,
using an internal static memory allocation will get erased leaving the function i suppose.
I notice i expressed myself in a bad way.

I meen with static as not using malloc like this.
char *myfunc()
{
char my_buff[512];
....fill the buff
return buff;
}

Did you understand it like that johnsfine? Your explanation makes sence to me but I want to be shore that we talk about the same static.
 
Old 08-14-2010, 01:23 PM   #4
wroom
Member
 
Registered: Dec 2009
Location: Sweden
Posts: 92

Rep: Reputation: 24
The declatation:
Code:
void function(void)
{
char my_buff[512];
}
declares buff using auto storage class. (Dynamic allocation). It will be optimized as much as the compiler can, and way of allocation may change depending on size of the variable or any other consideration of the compiler. Most often it will be allocated on the call stack, and scrapped when the function returns.

The following will declare buff as static, and reserve memory for this function to use for buff:
Code:
void function(void)
{
static char my_buff[512];
}
Caveats:
1)
Please be adviced as to check documentation for the compiler/linker you use, since different compilers/linkers have different allocation strategy. There exists compilers that treat function internal static variables like if they where auto/register without even giving out a warning. (This is mostly a problem with embedded systems programming, and not that often a problem in a desktop environment).
2)
If the program is multithreaded, or the function may get called recursively, the static declared storage will be overwritten by subsequent calls to the function.

Therefore it is deprecated to declare function internal static variables and returning pointer to its contents on return.
 
Old 08-14-2010, 01:24 PM   #5
orgcandman
Member
 
Registered: May 2002
Location: dracut MA
Distribution: Ubuntu; PNE-LE; LFS (no book)
Posts: 594

Rep: Reputation: 102Reputation: 102
Quote:
Originally Posted by wroom View Post
The declatation:
Therefore it is deprecated to declare function internal static variables and returning pointer to its contents on return.
I've never heard this. Can you point me to an RFC/Standard which states this?
 
Old 08-14-2010, 02:19 PM   #6
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by wroom View Post
Please be adviced as to check documentation for the compiler/linker you use, since different compilers/linkers have different allocation strategy. There exists compilers that treat function internal static variables like if they where auto/register without even giving out a warning.
I've never seen that. If true, such a compiler is broken.

Quote:
If the program is multithreaded, or the function may get called recursively, the static declared storage will be overwritten by subsequent calls to the function.
The data would be overwritten by subsequent calls even if the function is not recursive and the program is not multithreaded.

Maybe your point is that you might reasonably be able to design to finish using the data before it could be overwritten in a non recursive function in a single threaded program, but making sure the data isn't overwritten before you're done with it is a much more difficult constraint if recursive or multithreaded.

Quote:
Therefore it is deprecated to declare function internal static variables and returning pointer to its contents on return.
I don't think so.
 
Old 08-14-2010, 02:22 PM   #7
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by kalleanka View Post
Did you understand it like that johnsfine? Your explanation makes sence to me but I want to be shore that we talk about the same static.
Obviously not. I meant static as in wroom's example. I disagree with wroom's "Caveats" but wroom's example shows what I meant by static.
 
Old 08-14-2010, 03:45 PM   #8
wroom
Member
 
Registered: Dec 2009
Location: Sweden
Posts: 92

Rep: Reputation: 24
Quote:
Originally Posted by orgcandman View Post
I've never heard this. Can you point me to an RFC/Standard which states this?
Maybe wrong use of the word "deprecated". Sorry for that. Merely that it is not recommended for safe programming.

Added:
Of course one can use local static variables. In some cases one may not be allowed to use auto variables that allocate on stack. But my point is that the caller should allocate the space for the function to return data in, and not just trusting the allocation done in that function. The standard libraries are full of deprecated methods because they return pointers to local static data. Simply because they return pointers to local static data, and thus are not reentrant. One example of that is getdate() .

Last edited by wroom; 08-14-2010 at 04:42 PM.
 
Old 08-14-2010, 03:57 PM   #9
wroom
Member
 
Registered: Dec 2009
Location: Sweden
Posts: 92

Rep: Reputation: 24
Quote:
Originally Posted by johnsfine View Post
I've never seen that. If true, such a compiler is broken.
One could argue that. I certainly dont like when i have to work with design environments that deviate from standard. But working with embedded programming i have seen some examples of it. One good example is the C compilers available for Microchips eight bit MCU's. The reason for the deviation in that case being the sparse memory available, and the limited addressing capabilities of those MCU's.
But to make it worse when programming PIC Micros, one has to differ between pointers to const global and global data too.

Quote:
Originally Posted by johnsfine View Post
Maybe your point is that you might reasonably be able to design to finish using the data before it could be overwritten in a non recursive function in a single threaded program, but making sure the data isn't overwritten before you're done with it is a much more difficult constraint if recursive or multithreaded.
Exactly so.
 
Old 08-14-2010, 04:26 PM   #10
wroom
Member
 
Registered: Dec 2009
Location: Sweden
Posts: 92

Rep: Reputation: 24
And maybe it is good to add that a global static variable, (that is declared outside functions), is always initialized, to zero, or anything else if the linker is instructed to use a custom initializer. But a local static variable, (that is declared inside a function), need not be initialized when program starts, unless explicitly stated so, by for example "char b[9] = "good;" and still in some design environments this may generate a compile error instead.

Some older compilers tend to dislike local initializers, and one should know that it is a big difference between:
Code:
void function(void)
{
  int i = 0;
  while (i<1) ++i;
}
...and:
Code:
void function(void)
{
  int i;
  i = 0;
  while (i<1) ++i;
}
This is not a problem with modern compilers, but some of the older compilers will not accept the initializer in the local variable declaration.

In desktop environments local static is often initialized to zero anyhow, even if the linked in initializer doesn't, because the memory allocation in the OS wipes the memory before mapping it to the new process. Still, it is possible to turn off page scrubbing. In VMS the system administrator have the ability to choose with a single command wether page blocks will be scrubbed or not on allocation and/or freeing, and if it should simply be wiped once with zeroes, or follow DoD 5220.22-M standard for multiple pattern wiping. So it is better to be safe than sorry. And writing safe, portable code can be very frustrating sometimes.
 
Old 08-14-2010, 05:48 PM   #11
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

Code:
/* OK: caller allocates the memory */
char buf[512];
char * my_func(char* ret) /* called with "buf" */
{
  strcpy(ret, some_get_a_string_func()); /* assign the string pointer */
  return ret;
}
Code:
/* BAD!!!! This local variable is NOT VALID when my_func() returns */
char * my_func()
{
  char buf[512];
  strcpy(buf, some_get_a_string_func()); /* assign the string pointer */
  return buf;
}
Code:
/* Legal ... but not re-entrant.  
   Every call to "my_func()" will step on every other call.
   Definitely *NOT* OK with threads; probably not OK anywhere else  */
char * my_func()
{
  static char buf[512];
  strcpy(buf, some_get_a_string_func()); /* assign the string pointer */
  return buf;
}
Code:
/* Also OK: callee allocates memory; caller (or SOMEBODY!) needs to remember to free it. */
char * my_func(int max_bytes)
{
  char *buf = malloc (max_bytes + 1);
  if (buf)
  {
    /* assign string pointer 
       protect against buffer overflow
       insure return string is always NULL, or zero-terminated */
    strncpy(buf, some_get_a_string_func(), max_bytes); 
    buf[max_bytes] = '\0';
  }
  return buf ;
}

Last edited by paulsm4; 08-15-2010 at 06:28 PM.
 
Old 08-14-2010, 08:01 PM   #12
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
'malloc' call is also slow by definition because it's a system call.
 
Old 08-15-2010, 09:11 AM   #13
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 547

Original Poster
Rep: Reputation: 38
thanks paulsm4 for the 4 ways of (not) doing it. Is clear as cristal now.

Sloppy of me using the word static and not fixed length or something.
 
1 members found this post helpful.
Old 08-15-2010, 06:36 PM   #14
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, kalleanka -

Thanx for posting back.

FYI, I had a couple of (unintentional!) bugs in my sample code - I fixed them.

Also FYI, none of the examples (except for Example #2, the one commented "BAD!!!") is "wrong". All of them have different drawbacks and benefits, all of them are useful in different scenarios.

Even the "static" example. I'm doing maintenance programming on a DOS/Watcom C++ system (no kidding!) where using stack variables can literally crash the system. So I often have to declare stupid temp, debug variables as "static" variables, just because of limitations of the compiler and the architecture.

Please do mark the post as "Solved", and please feel free to "thank" anybody whose response helped.

PS:
And don't feel bashful about using "malloc()". It's almost never needed in C++ ... but it's perfectly appropriate and strongly encouraged in C.

IMHO .. PSM
 
Old 08-20-2010, 07:13 AM   #15
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 547

Original Poster
Rep: Reputation: 38
well i have to thank all of you here on the forum. I sitt alone and program and since i moved from my home contry i do not know anyone who does programming at all. So I only have forums to ask. And I want to get a good understanding not a quick fix since this will make me a better programmer. Hoppfully these threads will help others too.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help fixing C++ invalid conversion from const char* to char primerib Programming 26 03-10-2010 07:56 PM
error: invalid conversion from const char* to char* Dahakon Programming 1 08-31-2009 10:33 AM
How to return empty char * ? cpthk Programming 16 08-29-2009 12:17 AM
C++ Return Char Arrays (not with pointers) sadarax Programming 4 02-03-2006 05:49 PM
difference between function declaration: func() and func(void) koyi Programming 4 11-19-2005 11:19 AM


All times are GMT -5. The time now is 08:25 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration