C 释放分配的内存
通用条款4.4.5 c89 我有一个名为create_object的函数,为全局结构分配内存。我有一个名为destroy_object的函数,我检查指针是否为null,然后释放。以防万一,我会释放尚未分配的内存。然而,我已经通过连续两次调用销毁_对象来测试了这一点。但是,我在第二次调用时得到一个堆栈转储。但是,我确信它不会被释放,因为我已经将指针指定为NULL。所以它应该跳过free函数C 释放分配的内存,c,malloc,free,C,Malloc,Free,通用条款4.4.5 c89 我有一个名为create_object的函数,为全局结构分配内存。我有一个名为destroy_object的函数,我检查指针是否为null,然后释放。以防万一,我会释放尚未分配的内存。然而,我已经通过连续两次调用销毁_对象来测试了这一点。但是,我在第二次调用时得到一个堆栈转储。但是,我确信它不会被释放,因为我已经将指针指定为NULL。所以它应该跳过free函数 static struct Config_t { char protocol[LINE_SIZE];
static struct Config_t {
char protocol[LINE_SIZE];
char mode[LINE_SIZE];
} *app_cfg = NULL;
int create_object()
{
app_cfg = malloc(sizeof *app_cfg);
memset(app_cfg, 0, sizeof *app_cfg);
}
void destroy_config()
{
/* Check to see if the memory is ok to free */
if(app_cfg != NULL) {
free(app_cfg);
app_cfg = NULL;
}
}
非常感谢您的建议
=========================编辑==========
基本上,我在主函数中调用了create_object(),我做了一些处理,然后调用destory_object
int main(void)
{
create_object();
/* Do some processing on the structure */
destroy_object();
return 0;
}
========================================最终编辑====
静态结构配置{
字符协议[行大小];
字符模式[行大小];
}app_cfg[1]{{,'',''}
现在我没有使用malloc和free。在Cygwin下的gcc 3.3.3中使用这段代码对我来说是正确的,只要我调用它两次。您没有告诉我们您在这些函数之外做了什么,所以请先看一下,例如,您可能在调用之间意外地为app_cfg分配了一个垃圾非空值。此外,如果您没有使用“大名鼎鼎”的编译器,这可能是一个编译器错误(例如,它可能在编译时过于乐观,并假设您永远不会传递NULL来销毁配置)。试着输入以下内容:
void destroy_config()
{
/* Check to see if the memory is ok to free */
if(app_cfg != NULL) {
printf("not null\n" );
free(app_cfg);
app_cfg = NULL;
}else{
printf("null\n" );
}
}
看看它是否真的“知道”它何时为空。在Cygwin下的gcc 3.3.3中使用这段代码,在我两次调用它时,对我来说是正确的。您没有告诉我们您在这些函数之外做了什么,所以请先看一下,例如,您可能在调用之间意外地为app_cfg分配了一个垃圾非空值。此外,如果您没有使用“大名鼎鼎”的编译器,这可能是一个编译器错误(例如,它可能在编译时过于乐观,并假设您永远不会传递NULL来销毁配置)。试着输入以下内容:
void destroy_config()
{
/* Check to see if the memory is ok to free */
if(app_cfg != NULL) {
printf("not null\n" );
free(app_cfg);
app_cfg = NULL;
}else{
printf("null\n" );
}
}
看看它是否真的“知道”何时为空。我只有一个建议。不要为此分配内存,这是浪费精力 由于
app\u cfg
是一个文件级变量,您一次只能有一个副本,因此分配和取消分配它没有什么意义
只需将其创建为静态非指针并使用它:
static struct Config_t {
char protocol[LINE_SIZE];
char mode[LINE_SIZE];
} app_cfg;
您仍然可以提供一个create
和destroy
,它memset
将结构设置为零,但即使这样也可能不需要:
void create_object (void) {
memset(&app_cfg, 0, sizeof(app_cfg));
}
void destroy_config (void) {
memset(&app_cfg, 0, sizeof(app_cfg));
}
我只有一个建议。不要为此分配内存,这是浪费精力 由于
app\u cfg
是一个文件级变量,您一次只能有一个副本,因此分配和取消分配它没有什么意义
只需将其创建为静态非指针并使用它:
static struct Config_t {
char protocol[LINE_SIZE];
char mode[LINE_SIZE];
} app_cfg;
您仍然可以提供一个create
和destroy
,它memset
将结构设置为零,但即使这样也可能不需要:
void create_object (void) {
memset(&app_cfg, 0, sizeof(app_cfg));
}
void destroy_config (void) {
memset(&app_cfg, 0, sizeof(app_cfg));
}
在我看来这很好,您能发布使用此指针并调用
create\u object
和destroy\u config
的代码吗?此外,如果您想立即将分配给app\u cfg
的内存初始化为0s,您可以将malloc
和memset
调用组合成一个calloc
调用。另外,在空指针上使用free
也很好。将空指针传递到free()
是一个安全的禁止操作,因此您不需要在destroy\u config()
中进行空签入。您是否能够通过gdb运行代码,并在SIGSEGV引发后查看回溯?它是否指向程序中的任何其他位置?我觉得这很好,您可以发布使用此指针并调用create\u object
和destroy\u config
的代码吗?此外,如果您想立即将分配给app\u cfg
的内存初始化为0s,您可以将malloc
和memset
调用组合成一个calloc
调用。另外,在空指针上使用free
也很好。将空指针传递到free()
是一个安全的禁止操作,因此您不需要在destroy\u config()
中进行空签入。您是否能够通过gdb运行代码,并在SIGSEGV引发后查看回溯?它是否指向程序中的任何其他位置?memset
肯定不需要。因为它是静态的,所以保证为0填充。“而且销毁似乎也没有什么意义。”马修,我想的更多的是你希望在重新使用之前将其清除,而不是最初使用。但是,即使在创建/销毁时没有清除,优秀的程序员也不应该编写受遗留值影响的代码,因此我的“可能不需要”注释。我已经更改了源代码,并按照您的建议执行了操作。只有一个问题。在我的源代码中,我只需要struct变量的一个副本(堆栈级别,静态全局)。我想如果我创建了许多这种结构的对象,并希望它们在应用程序的生命周期中都可用。我想这是使用malloc的一个很好的理由?关于可能的重用,你有一个观点(尽管我不知道需要一个方法)。@ant2009:是的。如果您需要多个副本,您可以将它们malloc并从create\u which
返回指针。然后,有一个destroy\u which
来清理是很有用的,因为这意味着您可以随意更改代码而不影响API。memset
肯定是不需要的。因为它是静态的,所以保证为0填充。“而且销毁似乎也没有什么意义。”马修,我想的更多的是你希望在重新使用之前将其清除,而不是最初使用。但是,即使在创建/销毁时没有清除,优秀的程序员也不应该编写受遗留值影响的代码,因此我的“可能不需要”注释