如何防止 valgrind 将静态变量报告为泄漏?
How can I prevent valgrind from reporting static variables as leaks?
我有时使用静态变量只在实际调用函数时才进行昂贵的初始化,以避免每次调用都初始化。例如...
#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 中是否有更好的模式来避免重新初始化?
您的 指针 是静态的,但随后您通过调用 g_regex_new()
使其指向分配的缓冲区,并且 that必须释放缓冲区。
valgrind 具有 "suppression file" 功能。它是一个配置文件,指示 valgrind 应忽略某些内存分配,否则它会报告为泄漏。
在这种情况下,您将使用适当的指令指定内存分配来自您的 is_blank
() 函数,而不是来自 is_blank()
本身调用的任何其他函数,也许应该被忽略。
您将在 valgrind 的文档中找到有关抑制文件的更多信息。
最简单的做法是在全局或文件范围内定义这样的变量,然后在 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 *
的全局数组,它保留所有 static/global 分配的副本,这样你就可以稍后释放它们,并制作一个需要的函数新分配的指针并将其添加到列表中。
Glib 要求您在使用正则表达式后立即调用 g_regex_unref(GRegex *);
。因此,您需要某种机制来在您的程序完成之前进行此调用。
你可以有一个全局列表,你可以在其中存储正则表达式指针以最终取消引用它们,你可以有一个全局 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;
}
我有时使用静态变量只在实际调用函数时才进行昂贵的初始化,以避免每次调用都初始化。例如...
#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 中是否有更好的模式来避免重新初始化?
您的 指针 是静态的,但随后您通过调用 g_regex_new()
使其指向分配的缓冲区,并且 that必须释放缓冲区。
valgrind 具有 "suppression file" 功能。它是一个配置文件,指示 valgrind 应忽略某些内存分配,否则它会报告为泄漏。
在这种情况下,您将使用适当的指令指定内存分配来自您的 is_blank
() 函数,而不是来自 is_blank()
本身调用的任何其他函数,也许应该被忽略。
您将在 valgrind 的文档中找到有关抑制文件的更多信息。
最简单的做法是在全局或文件范围内定义这样的变量,然后在 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 *
的全局数组,它保留所有 static/global 分配的副本,这样你就可以稍后释放它们,并制作一个需要的函数新分配的指针并将其添加到列表中。
Glib 要求您在使用正则表达式后立即调用 g_regex_unref(GRegex *);
。因此,您需要某种机制来在您的程序完成之前进行此调用。
你可以有一个全局列表,你可以在其中存储正则表达式指针以最终取消引用它们,你可以有一个全局 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;
}