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

Problem between function pointers and [alleged] recursion.

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



Joined: 09 Aug 2004
Posts: 768
Location: Silicon Valley

View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger

Problem between function pointers and [alleged] recursion.
PostPosted: Wed Dec 25, 2013 8:51 pm     Reply with quote

Colleagues,

Here’s an example, where compiler suspects that the there may be recursion and generates an error “Recursion not permitted (function_name)”. But, the recursion doesn’t actually happen.

Arguments in this example only make function signatures distinct. They don’t serve any other purpose.

Code:
// Two different function pointers for completely different purposes.  Same signatures, but function with different purposes and same signatures aren't uncommon.
int8 (*g_fpFoo)(int8 a);
int8 (*g_fpBar)(int8 a);


int8 one_more_down();    // function prototype


int8 foo1(int8 a)
{
   return one_more_down();
}

int8 foo2(int8 a) {   return 2; }


int8 bar1(int8 a) {   return 11; }

int8 bar2(int8 a) {   return 12; }


int8 one_more_down()
{
   int8  iRet;
   iRet = (*g_fpBar)(42);
   return iRet;
}


void main()
{
   int8  i, k,
         iSomeCondition, iSomeOtherCondition;
   
   switch(iSomeCondition)  // initialize function pointer depending on some external condition
   {
   case 1:  g_fpFoo = foo1;   break;
   case 2:  g_fpFoo = foo2;   break;
   };

   switch(iSomeOtherCondition)    // initialize function pointer depending on some external condition
   {
   case 1:  g_fpBar = bar1;   break;
   case 2:  g_fpBar = bar2;   break;
   };

   while (1)
   {
      i = (*g_fpFoo)(k);   // make the call through the function pointer
   }
}


This generates an error "Recursion not permitted [foo1]". There's no actual recursion in this code, as you can see. Also, there's plenty of stack left. I've been trying to find the source of the problem for hours. Finally, I've tweaked the code so that is compiles and looked at the call tree. Here it is.



Every function with matching signature is on the list, even though only bar1 and bar2 may get called. There’s no actual recursion. But, the compiler suspect that there may be recursion.

Are there workarounds for this?

Any suggestion, insight or reference is really appreciated!

Cheers,
- Nick


PIC18F4550
4.081
_________________
Read the label, before opening a can of worms.
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Thu Dec 26, 2013 12:07 am     Reply with quote

Function pointers are not flawless in CCS. Recursion is not permitted and a call to a function pointer is actually calling a built in function. If you attempt to call it again you are inviting recursion.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Thu Dec 26, 2013 9:52 am     Reply with quote

To addon to what was said, the PIC micros don't natively support function pointers well. CCS has to do some tricky stuff to make it work on the architecture at all. One of those is an internal function it calls. If memory serves me correct, it is something like @gotoptr. Calling a recursive function within a recursive function calls @gotoptr inside @gotoptr, which is recursion.

So while it appears your methods don't recurse, they actually do in order to make function pointers work. It's a limitation of the hardware moreso than the compiler.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Dec 26, 2013 9:59 am     Reply with quote

The problem behind "recursion not allowed" is that CCS C allocates storage for local variables and function
arguments globally, analyzing the call tree to avoid memory conflicts.

Function pointers break the compiler's ability to determine the call hierarchy. As you probably already know,
giving a different function type to the second level functions by adding a dummy argument is a workaround for the
present example.
kender



Joined: 09 Aug 2004
Posts: 768
Location: Silicon Valley

View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger

PostPosted: Thu Dec 26, 2013 4:45 pm     Reply with quote

FvM wrote:
As you probably already know,
giving a different function type to the second level functions by adding a dummy argument is a workaround for the
present example.

Yes, I have thought about dummy parameters too. But, I was hoping that there may be a less hacky way.

It seems that making a typedef is enough to make the signatures distinct. The following compiles without a recursion error.

Code:
typedef  int8  fooParam;

int8 (*g_fpFoo)(fooParam a);
int8 (*g_fpBar)(int8 a);


int8 one_more_down();    // function prototype


int8 foo1(fooParam a)
{
   return one_more_down();
}

int8 foo2(fooParam a)  {   return 2;  }

// the rest of the example remains the same as in the O.P.

_________________
Read the label, before opening a can of worms.
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