【问题标题】:C array of pointers to functions pointers breaks program above certain length指向函数指针的 C 指针数组将程序中断超过一定长度
【发布时间】:2021-05-17 06:41:49
【问题描述】:

您好,我正在尝试从微控制器接收的字符串中调用函数。为此,微控制器 find 接收并将其与外围设备名称列表中的名称进行比较。它使用索引获取指向该外围设备可用的函数名称列表的指针,然后将函数名称与该列表进行比较以获得函数索引。然后使用这两个索引来调用函数。

系统在 2 个外设上工作正常,但添加第三个外设会导致程序停止运行,有时它会发出警告堆栈指针超出范围,有时它会在程序暂停时不显示任何位置。将第三个外设添加到 peripheral_fnct_pntr_pntr 列表会导致这种情况发生,它在 2 个外设的所有组合中都可以正常工作,并且注释该行也可以正常工作。

我为函数指针创建了自定义类型,如下所示:

typedef void (*fp)(int); //Declares a type of a void function that accepts an int
typedef char (*p)[6][20]; //pointer to array 

函数和指针列表的创建如下所示:

    char peripheral_names[6][20] = {"rgb","button"};  //[no of strs][size of str]
    char rgb_fnct_names[6][20] = {"rgb_brightness","red_brightness","green_brightness","blue_brightness","rgb_onTime","rgb_breath"};
    char led1_fnct_names[6][20] = {"led1_brightness","led1_onTime","led1_breath"};
    char led2_fnct_names[6][20] = {"led2_brightness","led2_onTime","led2_breath"};

        //store pointers linking name to functiion index to function
    //rgb led functions pointers
    fp rgb_fnct_pntrs[] = {&rgb_brightness,&red_brightness,&green_brightness,&blue_brightness,&rgb_on_time,&rgb_breath};

    
    //led function pointers
    fp led1_fnct_pntrs[] = {&led1_brightness,&led1_on_time};
    fp led2_fnct_pntrs[] = {&led2_brightness,&led2_on_time};
    
    //store list of ponters to peripheral function pointer lists
    fp *perph_fnct_pntr_pntr[]  = {rgb_fnct_pntrs, led1_fnct_pntrs, led2_fnct_pntrs};


    
   //store pointers linking peripheral name index to list of function names
   p name_to_fnct_lst[3]= {&rgb_fnct_names,&led1_fnct_names,&led2_fnct_names};

我不确定是什么导致了这个问题,因此我们将不胜感激。

【问题讨论】:

  • led1_fnct_pntrsled1_fnct_names 不匹配 ...以及许多其他不一致。
  • 函数名列表与在web服务器上的存储方式有关,所以不必匹配msp函数名,只要索引相同即可
  • 通常如果你的变量名中有一个数字,这意味着你真的想要一个以数字作为索引的数组。您可能会认为这只是风格狙击,但有时这样的事情会隐藏更基本的问题,并且在修复后会变得更加清晰。
  • 我建议 typedef 指针类型是一个坏主意,甚至更糟糕的数组类型。把类型全部写出来,我怀疑错误会变得更加明显。

标签: c pointers function-pointers microcontroller msp430


【解决方案1】:

我猜它的工作方式是,你从一个字符串开始,通过迭代name_to_fnct_lst[]找到匹配的字符串,然后搜索它指向的数组(rgb_fnct_namesled1_fnct_namesled2_fnct_names )。匹配时,您有两个索引(函数列表索引和列表中的名称)。

您使用第一个索引在perph_fnct_pntr_pntr 中查找函数指针列表,然后使用第二个索引在rgb_fnct_pntrsled1_fnct_pntrsled2_fnct_pntrs 中查找索引。

这适用于 rgb 情况,因为 rgb_fnct_namesrgb_fnct_pntrs 都有 6 个条目,但不适用于 led1/2 因为 led1_fnct_namesled2_fnct_names 有 3 个条目,但 led1_fnct_pntrsled2_fnct_pntrs 有2个条目。我跟对了吗?

如果是这样,解决方案似乎是将缺少的函数指针添加到 led1_fnct_pntrsled2_fnct_pntrs。或者它可能会简化将数组组合成char[3][6][20]fp[3][6] 数组的事情(在第一种情况下没有缺点,无论如何你都在分配未使用的字符,第二种情况会丢失一些你从中获得的未使用的指针地址更小的代码)。

另一种结构方式是:

struct f_nam_ptr {
    fp func;
    char name[20];
};
// Using a single map array here, or split it
// into rgb, led1, led2 maps.
struct f_nam_ptr f_nam_ptr_map[] = {
    { &rgb_brightness, "rgb_brightness" },
    // etc...
};

这样可以确保每个名称都有一个匹配的指针(并且不会浪费太多内存)。

【讨论】: