简体   繁体   中英

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. 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?

Alternatively, is there a better pattern in C to avoid reinitialization?

Glib requires you to call 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.

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.

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.

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

valgrind has a "suppression file" feature. It's a configuration file that instructs valgrind that certain memory allocations that it would otherwise report as leaks should be ignored.

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.

You will find more information about suppression files in valgrind's documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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