我想为C中的libcurl的进度信息编写回调函数的包装器。 这个包装器应该计算一些应该封装在库中的数据。
以下是对基本概念的描述:(我希望这能澄清事情)
用户应该实现一个回调函数xFunc并初始化一个数据结构来存储回调函数的数据(称为xData)。然后他应该调用包装函数aFunc。作为参数,他提供了一些与连接相关的数据以及指向xFunc和xData的指针。在aFunc中,计算了调用第二个函数bFunc所需的一些东西。 xFunc和xData指针也传递给此函数。在该函数中,初始化第二数据结构YData。此结构包含指向用户提供的xFunc和xData以及计算所需的一些其他数据的指针。现在libcurl相关的东西被初始化了。作为上传进度的回调,在库中实现了第二个回调函数yFunc。在此函数中,应使用xData和其他计算值调用用户提供的xFunc。
现在这里是我当前实现的代码(我删除了所有的计算代码并重命名了函数和结构,以便对上面的描述进行数学运算,所以它看起来有点奇怪。我希望它现在不太抽象):
main.c中
int xFunc(void *xData, long int param1, long int param2) {
//do something with the data
return 0;
}
int main(void){
xpData *xData;
xData->value = 0;
aFunc(xFunc, p);
return 0;
}
curlutils.h
typedef struct {
int value;
} xpData;
int xFunc(void *xData, long int param1, long int param2);
int aFunc(int (*xFunc)(void*, long int, long int), void xData);
int bFunc(int (*xFunc)(void*, long int, long int), void xData);
curlutils.c
typedef struct {
int (*xFunc)(void*, long int, long int);
void *data;
} ypData;
int yFunc(void *p, double dltotal, double dlnow, double ultotal, double ulnow){
ypData *pd;
pd = (ypData*) p;
return pd->xFunc(pd->data);
}
int bFunc(int (*xFunc)(void*, long int, long int), void xData){
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl){ //stripped many curl initialization stuff
ypData *yData;
yData->data = xData;
yData->xFunc = xFunc;
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, yFunc);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &yData);
curl_easy_perform(curl);
}
return 0;
}
int aFunc(int (*xFunc)(void*, long int, long int), void *xData){
//calculate something useful
bFunc(xFunc, xData);
return 0;
}
问题出在yFunc,我想调用xFunc。程序因错误而崩溃:
Illegal instruction
为什么这段代码不起作用?
答案 0 :(得分:1)
问题在于,当您将指针作为void指针传递时,如果传递错误类型的指针,则不会收到任何警告。然后当你转换指针时,你将其转换为错误的类型,并可能跳转到无效的地址。
你有:
ypData *yData;
yData->data = xData;
yData->xFunc = xFunc;
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, yFunc);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &yData);
这声明了一个locat指针var yData
但不初始化它。然后,您可以立即取消引用指针,这可能会崩溃(并且应该给出编译时警告)。如果没有,则您将&yData
(ypData **
)传递给yFunc
(间接通过curl_easy_setopt
),期望ypData *
为 ypData yData;
yData.data = xData;
yData.xFunc = xFunc;
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, yFunc);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &yData);
curl_easy_perform(curl);
它的论点。
您可以使用以下方法修复它:
curl
如果yData
函数之一将指针隐藏到curl
并且稍后yFunc
调用尝试在此函数返回后调用 ypData *yData = malloc(sizeof *yData);
yData->data = xData;
yData->xFunc = xFunc;
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, yFunc);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, yData);
,则存在潜在危险(指针悬空)。如果发生这种情况,您需要以下内容:
yData
有一个问题,你不知道何时释放分配的{{1}},因此会受到内存泄漏的影响。