简体   繁体   English

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

[英]How can I prevent valgrind from reporting static variables as leaks?

I sometimes use static variables to only do expensive initialization if the function is actually called, and to avoid initializing every call. 有时,我会使用静态变量仅在实际调用函数时才进行昂贵的初始化,并避免初始化每个调用。 For example... 例如...

#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);
}

Unfortunately valgrind will report them as memory leaks. 不幸的是,valgrind会将其报告为内存泄漏。 I don't consider static variables to be memory leaks. 我不认为静态变量是内存泄漏。

How can I prevent valgrind from reporting static variables as memory leaks without having to put in special suppressions for each one? 如何防止valgrind将静态变量报告为内存泄漏,而不必对每个变量进行特殊的抑制?

Alternatively, is there a better pattern in C to avoid reinitialization? 或者,C中是否有更好的模式来避免重新初始化?

Glib requires you to call g_regex_unref(GRegex *); Glib要求您调用g_regex_unref(GRegex *); as soon as you're done with a regex. 一旦完成了正则表达式。 Therefore, you need some mechanism to make this call before your program is done. 因此,在程序完成之前,需要某种机制来进行此调用。

You could either have a global list where you store the regex pointers to finally unref them, you can have the GRegex * pointer global where you can just use it to delete the obejct in the end, or you can refactor to have the pointer returned by a seperate function which you can use to unref. 您可能有一个全局列表,在其中存储了regex指针以最终取消对它们的引用,可以使GRegex *指针成为全局指针,您可以在其中最终使用它删除对象,也可以重构以使指针返回一个单独的函数,可以用来取消引用。

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;
}

The simplest thing to do is define variables like this at global or file scope, then clean them up in at atexit handler. 最简单的方法是在全局或文件范围内定义此类变量,然后在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();
    ...
}

If you want to get really fancy, you could have a global array of void * that keeps a copy of all static/global allocations so you can free them later, and make a function that takes the newly allocated pointer and adds it to the list. 如果您真的想花哨的话,可以有一个void *的全局数组,该数组保留所有静态/全局分配的副本,以便以后可以释放它们,并制作一个函数,该函数采用新分配的指针并将其添加到列表中。

您的指针是静态的,但是随后您可以通过调用g_regex_new()使其指向已分配的缓冲区,并且必须释放缓冲区。

valgrind has a "suppression file" feature. valgrind具有“禁止文件”功能。 It's a configuration file that instructs valgrind that certain memory allocations that it would otherwise report as leaks should be ignored. 这是一个配置文件,它指示valgrind应忽略某些可能因泄漏而报告的内存分配。

In this case, you would specify, using the appropriate directives, that memory allocations from your is_blank () function, but not from any other function that is_blank() itself calls, perhaps, should be ignored. 在这种情况下,您应该使用适当的指令指定is_blank ()函数的内存分配,而不是is_blank()本身调用的任何其他函数的内存分配,也许应该忽略。

You will find more information about suppression files in valgrind's documentation. 您将在valgrind的文档中找到有关禁止文件的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM