LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   return char* from func in c? (https://www.linuxquestions.org/questions/programming-9/return-char%2A-from-func-in-c-826209/)

kalleanka 08-14-2010 10:23 AM

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

johnsfine 08-14-2010 10:54 AM

Quote:

Originally Posted by kalleanka (Post 4066198)
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.

kalleanka 08-14-2010 11:08 AM

Thanks.

Quote:

Originally Posted by kalleanka (Post 4066198)
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.

wroom 08-14-2010 12:23 PM

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.

orgcandman 08-14-2010 12:24 PM

Quote:

Originally Posted by wroom (Post 4066277)
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?

johnsfine 08-14-2010 01:19 PM

Quote:

Originally Posted by wroom (Post 4066277)
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.

johnsfine 08-14-2010 01:22 PM

Quote:

Originally Posted by kalleanka (Post 4066228)
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.

wroom 08-14-2010 02:45 PM

Quote:

Originally Posted by orgcandman (Post 4066280)
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() .

wroom 08-14-2010 02:57 PM

Quote:

Originally Posted by johnsfine (Post 4066339)
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 (Post 4066339)
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.

wroom 08-14-2010 03:26 PM

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.

paulsm4 08-14-2010 04:48 PM

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 ;
}


Sergei Steshenko 08-14-2010 07:01 PM

'malloc' call is also slow by definition because it's a system call.

kalleanka 08-15-2010 08:11 AM

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.

paulsm4 08-15-2010 05:36 PM

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

kalleanka 08-20-2010 06:13 AM

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.


All times are GMT -5. The time now is 09:26 PM.