Microchip
直播中

张依然

8年用户 314经验值
私信 关注
[问答]

函数指针为空的问题

您好。我把函数指针作为参数传递给函数时遇到了一些问题。问题基本上是在一些循环下,函数指针是空的。最后检查代码和注释(1):(1)这是关键。如果我不使用这个句子,“数据”指针总是空的。使用时,“数据”具有正确的函数地址。我猜想编译器正在做一些它的优化魔术,因为函数指针没有被使用,它简单地丢弃它,默认情况下,它对函数地址无效。我记得在论坛的某个地方读到过这件事,但是我失去了线索。如果我使用函数(指针一旦设置或直接调用原始函数)在任何地方(内部或外部的函数)地址是可以的,但如果我不使用它…问题。我尝试禁用优化,但结果是一样的,NULL。欢迎任何想法或建议。TY。
                    
                    
以上来自于百度翻译

               
                                                                                      以下为原文

                                                                            Hello.

I'm having some problems with passing function pointers as parameter to function. The problem is basically under some circunstances the pointer to function is NULL. Check the code and note (1) at the end:


// function signature, quite simple
typedef void (* function_p)(void);

// just a simple function to check the function
void f1(void) // @ 0xAACC
{
    static int a = 0;
    a++;
}

// to manipulate the address (one of some tests)
volatile union {
    function_p function;
    uint16_t addr;  // I know they are so 16-bit address so, it's fine for the test
} ufun;

// gets a pointer to function (any) and simply fills the addr field in the union.
// for the simplicity it uses the signature above
void function_addr (const void * data)
{
    ufun.addr = data;
    if (ufun.addr) {
        //ufun.function(); // (1)
    }
}

void main(void)
{
  function_addr(f1);
  ufun.addr++;  // just to mess

  while(1);
}

(1) This is the key. If I don't use this sentence, "data" pointer is always NULL. When used, "data" has the correct function address.

I guess the compiler is doing some of its optimizing magic  and since the function pointer is not being used it

simply discards it and by default asigns NULL to the function address. I remember reading something about this in some place in the forum but I lost the thread. If I use the function (the pointer once it's set or just calling the original function directly) in any place (internal or externally to the function) the address is ok, but if I don't use it... problem.


I tried disabling optimizations but the result is the same, NULL.


Any idea or suggestion is welcome. Ty.

回帖(16)

杨玲

2018-8-24 16:05:30
开始摆脱这个。将指针指向函数/从指针转换为空洞是不合法的。也使你的计数器处于F1()的易失性,这样编译器就不会优化它。
                    
                    
以上来自于百度翻译

               
                                                                                      以下为原文

                                                                           

Start by getting rid of this.  It is not legal to convert a pointer to a function to/from a pointer to void.  Also make your counter in f1() volatile so the compiler doesn't optimize it away.
举报

朱瑞平

2018-8-24 16:12:05
我想我忘记了一些重要的事情:XC8V1.45,无论参数类型是什么,如果我不使用函数,它不知怎么地被传递为NULL;我也尝试使用函数指针作为参数类型:,具有相同的结果。计数器也是易失性的,全局的,静态的和组合的。NS。计数器只是在那里看到函数的效果,如果有的话(最初它是一个NOP)。我只是在其他编译器VC,Keil(ARM)中尝试过相同的代码…没问题,即使不使用调用,函数指针也会正确地传递(当然编译器在参数转换中抱怨,但是它们不通过NULL)。这只是XC8,但我不知道为什么。顺便说一下,所有这些都是默认设置,因为我只测试编译器如何用这些与硬件无关的C语句来操作。
                    
                    
以上来自于百度翻译

               
                                                                                      以下为原文

                                                                            I think I forgot something important to mention: XC8 v1.45
 
No matter what the parameter type is, if I don't use the function somehow it's passed as NULL;
I also tried using the function pointer as argument type: , with identical results.
 
As well, the counter was volatile, global, static and combinations. The counter is just there to see the effect of the function, if any (initially it was instead a NOP).
 
I just tried same code in other compilers VC, Keil (ARM)... no problem, the function pointer is passed correctly even without using the call (of course compilers complain in the parameter conversion, but they don't pass NULL). It's just XC8, but I don't why. Btw, all of them with default settings for all since I'm only testing how the compiler behaves with these C sentences not related to hardware at all.
举报

杨玲

2018-8-24 16:24:07
你所展示的代码没有任何副作用,所以你不能对它所做的有任何期望。事实上,它正确地做了什么,而不是按照你所期望的方式,这并不意味着编译器出现问题,它也不象另一个编译器。如果你纠正函数指针,使计数器易失,并调用函数,计数器增加吗?
                    
                    
以上来自于百度翻译

               
                                                                                      以下为原文

                                                                            The code you've shown has no side effects, so you can't have any expectations about what it does.  The fact that it correctly does nothing but not in the way you expect doesn't indicate a problem with the compiler, nor does it not behaving like another compiler.  If you correct the function pointer, make the counter volatile, and call the function, does the counter increment?
举报

朱瑞平

2018-8-24 16:36:53
如果函数执行,计数器将递增,但执行它必须不是空的。只有在执行前执行函数时才会发生。使我困惑的是什么。Ie:如果你已经定义了函数-AdDR,那么当调用主α1时,如果添加了一个间接函数调用,当调用时,第3个问题是第1个问题。它总是接收0x000,除非你提出一个调用先前函数(α2)或间接(α3)的句子。如果我定义了一个函数,并把它传递给一个函数,我希望它有地址,而不是0x000。看起来编译器正在优化它(如果我不记得其他线程坏了),并且因为函数不直接使用,并且没有直接分配给函数指针,所以它不被使用。所以…远离的。但我不确定是不是这样,或者是另一回事。因为禁用优化不会改变任何东西。PS:我讨厌脚本服务器…必须编辑5次才能“正确”。
                    
                    
以上来自于百度翻译

               
                                                                                      以下为原文

                                                                            The counter increments if the function executes, but to execute it must be not NULL.. and it only happens if the function is executed before asigning... what puzzles me. Ie:
 
If you have defined function_addr as follow,

void function_addr (const void * data)
{
    ufun.addr = data;
}


When calling in main
#1

main()
{
   function_addr(f1)  -> it receives NULL
}

 
 
#2

main
{
   f1()
   function_addr(f1)   -> it receives the correct address
}

 
 
Now, if an indirect function call is added as,
 

void function_addr (const void * data)
{
    ufun.addr = data;
 
    ufun.function();   <----
}

 
When calling,
#3

main()
{
   function_addr(f1) -> Receives correct address.
}

 
The problem is #1. It always receives 0x0000 unless you place a sentence calling the function previously (#2) or indirectly (#3). If I have a function defined and I pass it to a function I expect having the address, not 0x0000. Looks the compiler is optimizing it (if I dont remember bad from other threads), and since the function is not used directly and not assigned to a function pointer directly, it's "not" used.. so... removed. But I'm not sure if it is the case or is a different thing., since disabling optimizations does not change anything.
 
 
PS: I hate the script server....  had to edit 5 times to be "correct".
举报

更多回帖

发帖
×
20
完善资料,
赚取积分