大多数使用GTK的开源应用程序我都遇到了强制转换g_free作为GWeakNotify。 g_free的签名允许单个参数:g_free(),而GWeakNotify typedef允许两个:GWeakNotify。
我写了一个简单的程序来检查演员表,它看起来没问题 - 也就是说,第二个参数是'let through':
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
void
callFree(GWeakNotify notify, gpointer pData, GObject *pObject)
{
notify(pData, pObject);
}
int
main(int argc, char **argv)
{
(void)argc;
(void)argv;
gpointer pData = g_malloc(32);
GObject *pNull = (GObject *)g_malloc(64); //results in a 64B leak
if (!pData)
{
fprintf(stdout, "Unable to allocate pdata\n");
}
else
{
fprintf(stdout, "pData allocated OK...freeing\n");
callFree((GWeakNotify)g_free, pData, pNull);
}
return EXIT_SUCCESS;
}
我的问题是: 1)幕后发生了什么?第二个参数是否只是留在堆栈上而g_free不关心它(因为它不应该)?
2)为什么编译器在给出两个签名(g_free的1个参数和GWeakNotify的两个参数)时不会抱怨它?
谢谢! P
答案 0 :(得分:2)
这就是C调用约定的工作方式;调用代码将参数压入堆栈并再次清理它们。被调用的函数不关心有多少参数,它只使用它需要的参数。这就是printf()
之类的变量参数函数可以工作的方式。
由于GWeakNotify
强制转换,编译器并没有正确地抱怨它;基本上你是在告诉它“不要抱怨这些功能有不同的签名。”如果你遗漏演员,那就会抱怨。
(请注意,pData
永远不会在您的代码中NULL
; g_malloc()
如果无法分配请求的内存,则会中止该程序。如果您想要其他行为,请使用{ {1}}或常规g_try_malloc()
。)