将g_free转换为GWeakNotify的注意事项是什么?

时间:2012-03-09 01:57:04

标签: c glib calling-convention

大多数使用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

1 个答案:

答案 0 :(得分:2)

这就是C调用约定的工作方式;调用代码将参数压入堆栈并再次清理它们。被调用的函数不关心有多少参数,它只使用它需要的参数。这就是printf()之类的变量参数函数可以工作的方式。

由于GWeakNotify强制转换,编译器并没有正确地抱怨它;基本上你是在告诉它“不要抱怨这些功能有不同的签名。”如果你遗漏演员,那就会抱怨。

(请注意,pData永远不会在您的代码中NULL; g_malloc()如果无法分配请求的内存,则会中止该程序。如果您想要其他行为,请使用{ {1}}或常规g_try_malloc()。)