我的代码有一些奇怪的行为。 我不能将结构传递给回调函数。
#include <malloc.h>
#include "stdint.h"
typedef struct {
int test_rssi;
int setup_rssi;
} test_setup_scan_result;
typedef void (*WifiCallback)(uint8_t);
WifiCallback TestSetupCb;
void resume_configuration(test_setup_scan_result *result) {
if (result == NULL) {
printf("result is NULL\n");
return;
}
printf("result is not NULL\n");
printf("setup_rssi %d\n", result->setup_rssi);
printf("test_rssi %d\n", result->test_rssi);
printf("done");
}
void scan_test_setup_done_cb() {
printf("scan_done\n");
test_setup_scan_result *scan_result = malloc(sizeof(test_setup_scan_result));
printf("created structure\n");
scan_result->test_rssi = 1;
scan_result->setup_rssi = 1;
printf("filled structure\n");
if (TestSetupCb) {
printf("executing cb\n");
printf("setup_rssi %d\n", scan_result->setup_rssi);
printf("test_rssi %d\n", scan_result->test_rssi);
TestSetupCb((uint8_t) scan_result);
}
}
void scan_for_test_setup(WifiCallback cb) {
TestSetupCb = cb;
scan_test_setup_done_cb();
}
int main(void) {
printf("Hello World\n");
scan_for_test_setup((WifiCallback)resume_configuration);
return 0;
}
我试图获取resume_configuration
函数中的结构值后的代码不起作用。我是c语言的新手,所以任何有用文章的链接都被认为是。
答案 0 :(得分:1)
将函数名称转换为具有不兼容参数类型的函数指针类型未定义行为:
scan_for_test_setup((WifiCallback)resume_configuration);
// ^^^^^^^^^^^^^^
// Undefined behavior
这本身足以让人崩溃。但是,您的程序会非法执行另一项操作 - 下面的调用
TestSetupCb((uint8_t) scan_result);
// ^^^^^^^^^^^
// Does not fit in uint8_t
无论函数指针是否转换,都会失败,因为指针不适合8位。
答案 1 :(得分:1)
变量“scan_result”是指向具有堆区域中已分配内存空间的struct的指针。 当使用参数“(uint8_t)scan_result”调用TestSetupCb()时,实际上将“scan_result”的地址转换为uint8_t,这意味着获取地址的第一个字节并按值传递。在这种情况下,您将丢失要在resume_configuration()函数中处理的数据。 例如:当你将此地址转换为uint8_t时,假设“scan_result”结构地址为“0x004EE388”,结果为“0x00000088”,此地址无效并在程序中产生问题。此外,这种操作会对您的程序造成危险。 要解决您的问题,只需按以下方式重新定义函数指针: typedef void(* WifiCallback)(test_setup_scan_result *); 并更新你的代码:而不是TestSetupCb((uint8_t)scan_result);更改为TestSetupCb(scan_result);
答案 2 :(得分:0)
我在Valgrind中运行它并且我发现了一个明显的错误(在几个地方出现):
resume_configuration
不遵守WifiCallback
指针类型;它需要一个指针类型的参数,而不是uint8_t
类型的参数,它很可能具有不同的大小(它确实有)
您调用TestSetupCb((uint8_t) scan_result);
- 将scan_result
指针显式转换为小于指针的数据类型。您已截断指针,因此现在结果无法转换回有效指针。英特尔系统上的截断非常糟糕,任何结果指针都将始终位于NULL页面中。