While dealing with a library, in the provided example source code I found the following code:
在处理库时,在提供的示例源代码中我找到了以下代码:
x = (double *) malloc (narcs * sizeof (double));
dj = (double *) malloc (narcs * sizeof (double));
pi = (double *) malloc (nnodes * sizeof (double));
slack = (double *) malloc (nnodes * sizeof (double));
I've found nothing special here but when freeing memory, the source code example does the following:
我在这里找不到什么特别的东西,但在释放内存时,源代码示例执行以下操作:
free_and_null ((char **) &x);
free_and_null ((char **) &dj);
free_and_null ((char **) &pi);
free_and_null ((char **) &slack);
The free_and_null code is:
free_and_null代码是:
static void
free_and_null (char **ptr)
{
if ( *ptr != NULL ) {
free (*ptr);
*ptr = NULL;
};
};
My question is not why, when freeing the memory previously allocated, it is done a casting to a char double pointer. My question is why this is done this way, using a custom function to free the memory and why it was chosen a char **
as the argument of this function.
我的问题不是为什么,在释放先前分配的内存时,它会对char双指针进行转换。我的问题是为什么这样做是这样的,使用自定义函数释放内存以及为什么选择char **作为此函数的参数。
I know that certainly this question is happening because of my still limited knowledge of the C language, but anyway could anyone explain why this is done and if this is a good practice.
我知道当然这个问题正在发生,因为我对C语言的知识仍然有限,但无论如何,任何人都可以解释为什么这样做,如果这是一个好习惯。
3 个解决方案
#1
9
I have to agree with you - that code is a bit weird. There's no reason the author couldn't have used void **
just as easily.
我必须同意你的看法 - 代码有点奇怪。作者没有理由不能轻易地使用void **。
In addition, the if (*ptr != NULL)
check is unnecessary, since free(NULL)
is perfectly legal. The ;
characters after the braces aren't necessary either.
另外,if(* ptr!= NULL)检查是不必要的,因为free(NULL)是完全合法的。的;大括号后的字符也不是必需的。
A simpler version might look like this:
更简单的版本可能如下所示:
static void free_and_null(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
The reason this function exists at all is to make sure that freed pointers are set to NULL
, which is helpful for detecting use-after-free bugs and avoiding double-free bugs entirely.
这个函数存在的原因是确保释放的指针设置为NULL,这有助于检测释放后使用的错误并完全避免双重错误。
Edit: As StarPilot suggests below, it's probably a good idea to check that ptr
itself isn't NULL:
编辑:正如StarPilot在下面建议的那样,检查ptr本身不是NULL可能是个好主意:
static void free_and_null(void **ptr)
{
if (ptr)
{
free(*ptr);
*ptr = NULL;
}
}
#2
2
The reason for the extra level of indirection (**
) is because this allows the author of free_and_null to set the pointer to NULL. If they simply passed * or x they would have a copy of the pointer which is passed by value.
额外级别的间接(**)的原因是因为这允许free_and_null的作者将指针设置为NULL。如果它们只是传递*或x,它们将具有通过值传递的指针的副本。
static void
free_and_null (char *ptr)
{
if ( ptr != NULL ) {
free (ptr);
// *ptr = NULL; CAN'T DO THIS NOW
};
};
It's not a bad idea to reset pointers to NULL after the allocated memory has been freed as it can help detect memory leaks. I wouldn't follow the style of the author above exactly but I think this can help you understand the rationale. As Carl points out void **
would have been a more appropriate signature. You often see C code where people use char*
as a "generic" sort of pointer type - which is wrong, there's no good reason to use char in this context.
在释放已分配的内存后将指针重置为NULL并不是一个坏主意,因为它可以帮助检测内存泄漏。我不会完全遵循上面作者的风格,但我认为这可以帮助您理解其基本原理。正如卡尔指出的那样,**将是一个更合适的签名。你经常看到C代码,人们使用char *作为“通用”类型的指针类型 - 这是错误的,没有充分的理由在这种情况下使用char。
#3
0
Another approach, avoiding the pointer to pointer, would simply be:
避免指向指针的另一种方法就是:
void *free_and_null_back(void *p) {
free(p);
return NULL;
}
Usage:
用法:
p = free_and_null(p);
Or, for #define
fans:
或者,对于#define粉丝:
#define free(p) free(p);(p)=null;
Obviously that comes with all the usual caveats about the dangers of #define ...
显然,它伴随着关于#define危险的所有常见警告......
#1
9
I have to agree with you - that code is a bit weird. There's no reason the author couldn't have used void **
just as easily.
我必须同意你的看法 - 代码有点奇怪。作者没有理由不能轻易地使用void **。
In addition, the if (*ptr != NULL)
check is unnecessary, since free(NULL)
is perfectly legal. The ;
characters after the braces aren't necessary either.
另外,if(* ptr!= NULL)检查是不必要的,因为free(NULL)是完全合法的。的;大括号后的字符也不是必需的。
A simpler version might look like this:
更简单的版本可能如下所示:
static void free_and_null(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
The reason this function exists at all is to make sure that freed pointers are set to NULL
, which is helpful for detecting use-after-free bugs and avoiding double-free bugs entirely.
这个函数存在的原因是确保释放的指针设置为NULL,这有助于检测释放后使用的错误并完全避免双重错误。
Edit: As StarPilot suggests below, it's probably a good idea to check that ptr
itself isn't NULL:
编辑:正如StarPilot在下面建议的那样,检查ptr本身不是NULL可能是个好主意:
static void free_and_null(void **ptr)
{
if (ptr)
{
free(*ptr);
*ptr = NULL;
}
}
#2
2
The reason for the extra level of indirection (**
) is because this allows the author of free_and_null to set the pointer to NULL. If they simply passed * or x they would have a copy of the pointer which is passed by value.
额外级别的间接(**)的原因是因为这允许free_and_null的作者将指针设置为NULL。如果它们只是传递*或x,它们将具有通过值传递的指针的副本。
static void
free_and_null (char *ptr)
{
if ( ptr != NULL ) {
free (ptr);
// *ptr = NULL; CAN'T DO THIS NOW
};
};
It's not a bad idea to reset pointers to NULL after the allocated memory has been freed as it can help detect memory leaks. I wouldn't follow the style of the author above exactly but I think this can help you understand the rationale. As Carl points out void **
would have been a more appropriate signature. You often see C code where people use char*
as a "generic" sort of pointer type - which is wrong, there's no good reason to use char in this context.
在释放已分配的内存后将指针重置为NULL并不是一个坏主意,因为它可以帮助检测内存泄漏。我不会完全遵循上面作者的风格,但我认为这可以帮助您理解其基本原理。正如卡尔指出的那样,**将是一个更合适的签名。你经常看到C代码,人们使用char *作为“通用”类型的指针类型 - 这是错误的,没有充分的理由在这种情况下使用char。
#3
0
Another approach, avoiding the pointer to pointer, would simply be:
避免指向指针的另一种方法就是:
void *free_and_null_back(void *p) {
free(p);
return NULL;
}
Usage:
用法:
p = free_and_null(p);
Or, for #define
fans:
或者,对于#define粉丝:
#define free(p) free(p);(p)=null;
Obviously that comes with all the usual caveats about the dangers of #define ...
显然,它伴随着关于#define危险的所有常见警告......