如何防止valgrind将静态变量报告为泄漏?

时间:2016-01-09 02:37:35

标签: c valgrind c99

我有时会使用静态变量来执行昂贵的初始化,如果实际调用该函数,并避免初始化每个调用。例如......

#include <glib.h>
#include <stdbool.h>

bool is_blank(char *line) {
    static GRegex *blank_line_re = NULL;

    if( !blank_line_re ) {
        blank_line_re = g_regex_new(
            "^ \\s* $",
            G_REGEX_OPTIMIZE | G_REGEX_EXTENDED,
            0,
            NULL
        );
    }

    return g_regex_match(blank_line_re, line, 0, NULL);
}

不幸的是,valgrind会将它们报告为内存泄漏。我不认为静态变量是内存泄漏。

如何防止valgrind将静态变量报告为内存泄漏而不必为每个变量添加特殊抑制?

或者,C中是否有更好的模式以避免重新初始化?

4 个答案:

答案 0 :(得分:3)

Glib要求您在使用正则表达式后立即致电g_regex_unref(GRegex *);。因此,在程序完成之前,您需要一些机制来进行此调用。

你可以有一个全局列表,你可以存储正则表达式指针,最后取消它们,你可以将GRegex *指针全局放在哪里,你可以用它来删除最终的obejct,或者你可以重构让一个单独的函数返回指针,你可以使用它来取消。

GRegex * my_blank_reg()
{
  static GRegex *blank_line_re = NULL;
  if (!blank_line_re) 
  {
    blank_line_re = g_regex_new(
      "^ \\s* $", G_REGEX_OPTIMIZE | G_REGEX_EXTENDED,  
      0, NULL);
  }
  return blank_line_re;
}

bool is_blank(char *line) 
{
  return g_regex_match(my_blank_reg(), line, 0, NULL);
}

void free_static()
{
  g_regex_unref(my_blank_reg());
}

int main()
{
  // do stuff with is_blank()

  free_static();
  return 0;
}

答案 1 :(得分:2)

最简单的方法是在全局或文件范围定义这样的变量,然后在atexit处理程序中清理它们。

struct s *s1 = NULL;
struct s *s2 = NULL;

void free_global(void)
{
    free(s1);
    free(s2);
}

...
void f1(void)
{
    s1 = malloc(sizeof(struct s));
}

void f2(void)
{
    s2 = malloc(sizeof(struct s));
}

...

int main(void)
{
    atexit(free_global);
    ...
    f1();
    ...
    f2();
    ...
}

如果你想变得非常花哨,你可以拥有一个void *的全局数组,它保存所有静态/全局分配的副本,以便你以后可以释放它们,并创建一个带有新分配指针的函数并将其添加到列表中。

答案 2 :(得分:0)

你的指针是静态的,但是你通过调用g_regex_new()使它指向一个已分配的缓冲区,并且 缓冲区必须被释放。

答案 3 :(得分:0)

valgrind有一个“抑制文件”功能。这是一个配置文件,它指示valgrind应该忽略它否则会报告为泄漏的某些内存分配。

在这种情况下,您将使用适当的指令指定来自is_blank()函数的内存分配,但不能指定is_blank()本身调用的任何其他函数的内存分配

您可以在valgrind的文档中找到有关抑制文件的更多信息。