问题语句:我正在初始化代码中的回调ops->cmd = pando_entry_cb
,但由于指针类型不兼容,我得到了未定义的行为。我知道问题是什么,但不知道我的代码中有什么错误。
下面提供的代码给出了 UB。我想知道如何纠正它。
UB 代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
typedef struct proc proc_t;
typedef struct proc_ops proc_ops_t;
proc_t *proc_new(proc_ops_t *ops);
struct proc_ops {
//this is the callback
int (*cmd)(proc_ops_t *ops, const void *tx_buf, unsigned tx_count, void *rx_buf, unsigned *rx_count);
void *priv;
};
struct proc {
proc_ops_t *ops;
};
//EDIT: Changed the return type
static int pando_entry_cb(proc_t *proc, const void *tx_buf, unsigned tx_count,
void *rx_buf, unsigned *rx_count) {
printf("CB Entry point is calledn");
printf("FROM_CB: D_proc: tx: %p, t_count: %d, rx :%p, r_count: %pn", tx_buf,
tx_count, rx_buf, rx_count);
//EDIT
return 1;
}
int proc_cmd(proc_t *proc, const void *tx_buf, unsigned tx_count,
void *rx_buf, unsigned *rx_count) {
int r;
char s[256];
printf("D_proc: tx: %p, t_count: %d, rx :%p, r_count: %pn", tx_buf,
tx_count, rx_buf, rx_count);
r = proc->ops->cmd(proc->ops, tx_buf, tx_count, rx_buf, rx_count);
if (r < 0) {
return -1;
}
//EDIT : Added the return type
return 0;
}
proc_t *proc_new(proc_ops_t *ops) {
proc_t *proc = malloc(sizeof(*proc));
printf("Hello allocating the memory to proc structn");
if (!proc) {
printf("LOG_ERR :%s: malloc failed", __func__);
return NULL;
}
memset(proc, 0, sizeof(*proc));
//intitalize the struct callback and opaque pointer
// problem is here where callback assignment from incompitable pointer type
// Getting UB, here I know the pointer assignment isn't matching.
// problem what I'm facing is this : If a converted pointer is used to call a function
// whose type is not compatible with the referenced type, the behavior is undefined.
ops->cmd = pando_entry_cb; // <-- UB
ops->priv = proc;
return proc;
}
int main() {
proc_t *proc;
proc_ops_t *ops;
// EDIT: Allocated the memory to ops
proc_ops_t *ops = malloc(sizeof(*ops));
memset(ops, 0, sizeof(*ops));
proc = proc_new(ops);
if (!proc) {
return -1;
}
//Here I typecasted to void * to match the signature of function.
proc_cmd(proc, (void*)8, 4, 0, 0);
return 0;
}
希望我的预期输出如下所示:
Hello allocating the memory to proc struct
D_proc: tx: 0x8, t_count: 4, rx :(nil), r_count: (nil)
CB Entry point is called
FROM_CB: D_proc: tx: 0x8, t_count: 4, rx :(nil), r_count: (nil)
我会很棒,有人指出我做错了什么?
编辑:
- 我将函数指针的返回类型和初始化的函数更改为与 int 相同的类型。
- 已将内存分配给我错过的对象。
- 将返回类型添加到我的函数
int proc_cmd()
不过,我还是得到了UB。
感谢您的帮助。
将cmd
的数据类型与您尝试分配给它的函数进行比较
int (*cmd)(proc_ops_t *ops, const void *tx_buf, unsigned tx_count, void *rx_buf, unsigned *rx_count);
static void pando_entry_cb(proc_t *proc, const void *tx_buf, unsigned tx_count, void *rx_buf, unsigned *rx_count)
返回类型不同,第一个参数的类型也不同。您的代码期望该函数返回某些内容,因此您绝对应该让它返回一个int
,即使这总是0
。
然后在proc_cmd
中,它只在r
为负时返回一些东西。同样,您应该让它返回0
或者如果适用,则返回r
的实际值。
此外,您将一个未分配的值传递到proc_new
因为ops
在我可以看到的代码中的任何点都没有分配。
最后,当您创建proc_t
时,您不会填充它的副本ops
因此当您稍后使用它时,它不会被设置。您希望在返回之前将此行添加到proc_new
末尾。
proc->ops=ops;
我没有尝试过你的代码,但我知道函数指针的返回类型必须与它指向的函数的返回类型匹配。 例如 void (*func)()
可以指向任何返回 void 的函数,但不能指向返回 int 的函数。就此而言,您需要int (*func)()
或int (*func)(<list of arguments>)
。没有参数列表的函数指针类型与它所指向的函数的数量和参数类型无关,但带有参数的函数必须匹配(感谢@John Bollinger指出这一点。请参阅评论。请注意,由于函数指针不携带有关参数的信息,因此参数是默认提升的。
我还可以提到,C++(默认情况下(将使用没有参数列表的函数指针指向带有参数的函数视为错误。虽然问题是关于 C 的,但我发现了解使 C 不是C++子集的情况很有用。