CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

char* func(void) PIC18F2525 vs. PIC24FJ...

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Prefekt



Joined: 21 Oct 2010
Posts: 85

View user's profile Send private message

char* func(void) PIC18F2525 vs. PIC24FJ...
PostPosted: Sun Nov 18, 2018 8:38 am     Reply with quote

If I run this code on a PIC24FJ...
Code:

char* func(void){
   char ret[25];
   sprintf(ret, "function1");
   return ret;
}

void main()
{
   
   while(1){
      fprintf(PORT1, "ret: %s\r", func());
      delay_ms(1000);
 }

the print is : "function1"


If I run this on a PIC18F2525 the print is: "L<2>nction1"
<2> is HEX 02;

The first 2 chars are anything but not "fu", why?
Ttelmah



Joined: 11 Mar 2010
Posts: 19512

View user's profile Send private message

PostPosted: Sun Nov 18, 2018 9:03 am     Reply with quote

There is an issue with what you are trying to do.

The array 'ret', is only reseved while you are physically running code inside the function 'func'. The memory area it uses can be re-used as soon as you exit the function. Problem is that if the compiler decides to use this area for something else (like temporary storage in the fprintf), the data stored here will be corrupted....

If you want to return a pointer to a char array from a function, this needs to be to a static array, or a RAM area that has perhaps been allocated by malloc. Otherwise the data can become overwritten....

On the PIC24, the stack is used for temporary storage, so it happens not to be overwriting the area. The PIC18, happens to be re-using this area.
Prefekt



Joined: 21 Oct 2010
Posts: 85

View user's profile Send private message

PostPosted: Sun Nov 18, 2018 9:56 am     Reply with quote

Thanks for the explanation.

Is this only an issue in the compiler version for PIC10/1216/18 or also for PIC24?
Ttelmah



Joined: 11 Mar 2010
Posts: 19512

View user's profile Send private message

PostPosted: Sun Nov 18, 2018 10:24 am     Reply with quote

Technically for everything.

You have to understand how RAM is used. There is a 'pool' of available RAM, and when a variable is allocated, it uses space inside this. While you are in the function that uses it, or any 'sub function', this is maintained and protected from re-use. As soon as you exit the function that allocated this RAM, it becomes available for other functions to use.
If you look in the 'symbols' list you will find the address being allocated. So there will be an entry for func.ret, and an address where this is stored. You will then probably find that there is an entry like @FPRINTFxxxxx.xxx which is allocated the same RAM.
This is the 'scope' of the variable.

A static variable has an allocation that is permanent, and therefore reserved from any other use.

The same happens on C compilers on the PC etc.. Returning a pointer to a local variable, is a 'well known' error in C programming.

<https://stackoverflow.com/questions/19042552/returning-a-pointer-of-a-local-variable-c>

Your pointer is copied, but it points to an area that is no longer preserved.

This is not a feature of a particular chip, it's a feature of C....
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Sun Nov 18, 2018 10:45 am     Reply with quote

Scope and lifetime of variables is something you should study.
There's another way to get around this, but you no longer have a return value. Instead, you pass the pointer to an array to func() as a parameter. Since arrays are passed by reference, you will modify that array, and also the array will still be in scope when you exit the function.

Code:
void func(char *ret){
   sprintf(ret, "function1");
}

void main()
{
   char mystr[25];
   while(1){
      func(mystr);
      fprintf(PORT1, "ret: %s\r", mystr);
      delay_ms(1000);
 }
}
Prefekt



Joined: 21 Oct 2010
Posts: 85

View user's profile Send private message

PostPosted: Sun Nov 18, 2018 11:10 am     Reply with quote

Ah, yes I remember.
Normally I develop in c#.

Thank you for support!
Ttelmah



Joined: 11 Mar 2010
Posts: 19512

View user's profile Send private message

PostPosted: Sun Nov 18, 2018 11:32 am     Reply with quote

C#, explicitly does not allow returning references to local variables, by
reference. This is done to ensure that a reference cannot outlive the
referenced variable.
Because of this the returned variable always physically points to data,
and is therefore 'protected' from re-use so long as this exists.
The allocation is by 'data use' and so long as something is still using the
data, it is protected.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group