This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to solove warning recursive call to a constant

I have following codes:

void fun1(unsigned char *msg);

void fun2()
{
fun1("ssss");
}
void fun3()
{
}
code void (*func_array[])()={fun2, fun3};

void fun1( unsigned char *msg)
{
(*func_array[1])();
}

void main()
{
(*fun_array[0])();
}

when compiling, i got the following message
*** WARNING L13: RECURSIVE CALL TO SEGMENT
SEGMENT: ?CO?HELLO

Could you please tell me how to solve it? Thanks a lot!

  • I think my situation is a little different from what those APP discuss.

    PROGRAM RECURSIONS REMOVED FROM CALL TREE
    =========================================
    +--> ?CO?HELLO
    |  | ?PR?FUN2?HELLO
    <--+ ?PR?_FUN1?HELLO
    

    I also check the caller tree, i feel that fun1 overlay has some problem. a strage symbol comes out _fun1, but i don't know how to fix it? pls help. Thanks


    SEGMENT BIT_GROUP DATA_GROUP
    +--> CALLED SEGMENT START LENGTH START LENGTH
    ------------------------------------------------------------------
    ?C_C51STARTUP ----- ----- ----- -----
    +--> ?PR?MAIN?HELLO

    ?PR?MAIN?HELLO ----- ----- ----- -----
    +--> ?CO?HELLO
    +--> ?PR?PRINTF?PRINTF

    ?CO?HELLO ----- ----- ----- -----
    +--> ?PR?FUN2?HELLO
    +--> ?PR?FUN3?HELLO

    ?PR?FUN2?HELLO ----- ----- ----- -----
    +--> ?PR?_FUN1?HELLO

    ?PR?_FUN1?HELLO ----- ----- 0008H 0003H

    ?PR?PRINTF?PRINTF 0020H.0 0001H.1 0008H 0014H
    +--> ?PR?PUTCHAR?PUTCHAR

  • Why don't you cut and paste the code that you are actually using?

  • because the original code is too complex! I am afraid that you guys may lose interests!

    I use two function pointer tables, so recursive calls problem comes out! Can you please tell me where can I find examples of how to use multi-function pointer tables and one table depends on the other table. Thanks a lot!

  • use two function pointer tables

    That is PC C, not '51 C

    Mend your ways and adapt your coding style to the processor you are using. Practices like that can kill a '51 better than a voltage surge.

    Erik

  • If the techniques in the aforementioned App. Note #129 do not suit you, an alternative is to codify the function pointer array at the cost of an additional pushed return address.

    void func_array(unsigned char idx)
    {
        switch (idx)
        {
        case 0: fun2(); break;
        case 1: fun3(); break;
        case 2: fun4(); break;
        case 3: fun5(); break;
        case 4: fun6(); break;
        /* ... */
        }
    }
    

  • "...codify the function pointer array..."

    That is, if your function pointer arrays are constant (i.e., are not modified during runtime).

  • If you dynamically update the function pointer table, then there is no way for the static call tree analysis to help you. So, you'll be in for a lot of work with the OVERLAY directive, or else a lot of code bloat from the reentrant declaration. Unless you're doing extremely dynamic things like creating code to execute on the fly, you probably know the range of possible results, and can use an index into a table of fixed pointers. "Call func 3" works about as well as "Call func *p" in most cases.

    It's perhaps worth noting that a switch statement such as the one Dan posted generally compiles into a jump table anyway. You don't have to explicitly code a function pointer table to get a table of function pointers.

    I often get a recursive call to segment warning from code with structure like this:

    char const code * code StringTable[] =
       {
       "Name1",
       "Name2"
       }
    
    void f1 (int i)
       {
       printf (StringTable[i]);
       }
    
    void f2 (int i)
       {
       PerformWonders(i);
       }
    
    const code FuncTableEntry FuncTable[2] =
       { f1, f2 };
    
    void Dispatcher (void)
       {
       FuncTable(i);
       }
    

    That is, to be more brief, a const table of function pointers in a particular module. The Keil compile can figure out the call tree below Dispatcher, because the table is static file scope and constant. However, the function pointer table and the string constants reside in the same constant segment. So, f1 and f2 are marked as referring to their own segment, because of the reference to the string constants, and the linker thus dutifully produces a warning about recursive calls. There are no actual recursive calls in the code per se, just a reference from one item in the constant segment to another.

    There is no way to identify and selectively disable warning 13 in just these cases, so I unfortunately wind up shutting down all the recursive warnings. The alternative would be to break out the string constants and function table into seperate .c files so that they can appear in different segments, but that brings along all the usual problems of namespace clutter and lack of modularity that we're used to seeing in the "eliminate dead code" threads.

  • Thank you all guys!
    I cut and paste part of my codes and solution here. HOPE that you still keep one eye on that, and any suggestion is very welcome!

    The situation is the codes are not only intended for C51, but also for other processor! I prefer a general structure for all platforms, and It seem that using two function pointer tables is a good way.

    Firstly, I have the following data structure for function pointer tables.

    …….
    typedef Bool (*FnDrawing)(Void);
    typedef Void (*FnDrawed)(Void);
    typedef Bool (*FnProcessingKey)(Void);
    typedef Void (*FnProcessedKey)(Void);
    ……….
    
    typedef struct tagStruct
    {
        …………………..
        FnProcessingKey            fnProcessingKey;
        FnProcessedKey             fnProcessedKey;
        FnDrawing           fnDrawing;
        FnDrawed            fnDrawed;
       …………………
    } nuStruct;
    typedef nuStruct * RPnuStruct;
    

    And then I have several function pointer tables.
    Code nuStruct MainStruct =
    {
    …………..
        MainProcessingKey,
        MainProcessedKey,
        MainDrawing,
        MainDrawed,
    …………………….
    };
    
    Code nuStruct TnuStruct =
    {
        …………..,
        TProcessingKey,
        TProcessedKey,
        TDrawing,
        TDrawed,
    ………………
    };
    ……
    


    Base on that, I construct another table
    Code nuStruct * Code c_nuTable[] =
    {
               ……………….
    	&MainnuStruct,
                ……………
    	&TnuStruct,
    	…………..
    };
    


    Depending on different situation, I will select different function from nuStruct to run. Unlucky, in subroutine of some functions of table such as TProcessedKey , I need to look up the table again! So recursive call problem comes out.


    Now my solution is


    Use overlay directive to delete reference between LOOK-UP TABLE and its caller, and then add reference between each function manually! It is a very trial task which costs me half a day, but now seem it works!

  • It is a very trial task which costs me half a day,
    That is the cost of programming a '51 as if it were a PC.

    Erik

  • Dan: "... codify the function pointer array at the cost of an additional pushed return address."

    Drew: "It's perhaps worth noting that a switch statement such as the one Dan posted generally compiles into a jump table anyway."

    And when it compiles into a jump table, it does not cost an additional pushed return address.