在 c 中的破坏函数中使用 free() 后内存泄漏(根据夹板)
Memory leak after using free() in destroyer function in c (according to splint)
我正在重新学习 C,并使用 splint
来测试我的源代码。
我正在尝试执行以下操作:
- 创建具有 "constructor" 函数的结构
- 用"destructor"函数销毁结构,释放结构的内存。
但是,当我使用 splint 测试我的代码时,它会发出与析构函数中的临时存储相关的警告,以及调用析构函数后的内存泄漏。
我想知道 (a) splint 关于我代码中内存泄漏的说法是否正确(我认为不是),以及 (b) 我应该怎么做,要么修复我的代码,要么让 splint 理解我的意思正在做。
无论如何,这是代码:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
// define the structure
struct Boring {
int amount;
};
// the creator
static struct Boring *Boring_create(int amount) {
struct Boring *really = malloc(sizeof(struct Boring));
assert(really != NULL);
really->amount=amount;
return really;
}
// the destroyer
static void Boring_destroy(struct Boring *really) {
assert( really != NULL );
// free the memory of the Boring structure
free(really);
}
int main( /*@unused@*/ int argc, /*@unused@*/ char *argv[]) {
int amount = 5;
struct Boring *tv = Boring_create(amount);
printf("The TV is boring level %d\n",tv->amount);
// destroy the tv!
Boring_destroy(tv);
printf("The TV is now boring level %d\n",tv->amount);
return 0;
}
/* Output */
/*
* $> ./destroytv
* The TV is boring level 5
* The TV is now boring level -538976289 (or 0 depending on OS/compiler)
*/
代码使用 gcc 编译和运行良好。
但是,当我使用夹板对其进行测试时,夹板发出以下警告:
$> splint boringtv.c
destroytv.c: (in function Boring_destroy)
destroytv.c: Implicitly temp storage really passed as only param: free (really)
Temp storage (associated with a formal parameter) is transferred to a new non-temporary reference. The storage may be released or new aliases crated. (Use -temptrans to inhibit warning)
destroytv.c: (in function main)
destroytv.c: Fresh storage tv not released before return
A memory leak has been detcted. Storage allocated locally is not released before the last reference to it is lost (use -mustfreefresh to inhibit warning)
Fresh storage tv created
第一次警告,越想越不明白。但是我没有阅读足够的手册来证明关于那个的适当问题。
第二个警告,关于内存泄漏,似乎splint只是没有意识到内存被释放到别处,这对我来说似乎很奇怪。如果我在 main
.
内调用 free()
,警告就会消失
在此先感谢您的帮助。请让我知道更多详细信息(例如警告的行号)是否有帮助。
与怀疑的一样,没有内存泄漏。
为了告诉 splint
哪个函数应该控制结构的内存,析构函数的输入应该用 /*@only@*/
注释。
static void Boring_destroy( /*@only@*/ struct Boring *really ) {...
这告诉 splint
该函数正在单独控制变量,从而允许它和平地释放内存而不会引发任何警告。
更具体地说,唯一的注释'indicate[s] a reference is the only pointer to the object it points to.'(夹板手册)
注释删除了原始问题中提到的两个警告,并将它们替换为指示 tv
在被销毁后正在使用的警告。这个新警告是可取的,因为正如 WhozCraig 在评论中提到的,一旦内存被释放就调用内存是未定义的行为,因此应该避免。
参考文献:
- SO questioin about splint and memory ownership
- splint manual(参见 5.2.1. 非共享引用)
我正在重新学习 C,并使用 splint
来测试我的源代码。
我正在尝试执行以下操作:
- 创建具有 "constructor" 函数的结构
- 用"destructor"函数销毁结构,释放结构的内存。
但是,当我使用 splint 测试我的代码时,它会发出与析构函数中的临时存储相关的警告,以及调用析构函数后的内存泄漏。
我想知道 (a) splint 关于我代码中内存泄漏的说法是否正确(我认为不是),以及 (b) 我应该怎么做,要么修复我的代码,要么让 splint 理解我的意思正在做。
无论如何,这是代码:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
// define the structure
struct Boring {
int amount;
};
// the creator
static struct Boring *Boring_create(int amount) {
struct Boring *really = malloc(sizeof(struct Boring));
assert(really != NULL);
really->amount=amount;
return really;
}
// the destroyer
static void Boring_destroy(struct Boring *really) {
assert( really != NULL );
// free the memory of the Boring structure
free(really);
}
int main( /*@unused@*/ int argc, /*@unused@*/ char *argv[]) {
int amount = 5;
struct Boring *tv = Boring_create(amount);
printf("The TV is boring level %d\n",tv->amount);
// destroy the tv!
Boring_destroy(tv);
printf("The TV is now boring level %d\n",tv->amount);
return 0;
}
/* Output */
/*
* $> ./destroytv
* The TV is boring level 5
* The TV is now boring level -538976289 (or 0 depending on OS/compiler)
*/
代码使用 gcc 编译和运行良好。
但是,当我使用夹板对其进行测试时,夹板发出以下警告:
$> splint boringtv.c
destroytv.c: (in function Boring_destroy)
destroytv.c: Implicitly temp storage really passed as only param: free (really)
Temp storage (associated with a formal parameter) is transferred to a new non-temporary reference. The storage may be released or new aliases crated. (Use -temptrans to inhibit warning)
destroytv.c: (in function main)
destroytv.c: Fresh storage tv not released before return
A memory leak has been detcted. Storage allocated locally is not released before the last reference to it is lost (use -mustfreefresh to inhibit warning)
Fresh storage tv created
第一次警告,越想越不明白。但是我没有阅读足够的手册来证明关于那个的适当问题。
第二个警告,关于内存泄漏,似乎splint只是没有意识到内存被释放到别处,这对我来说似乎很奇怪。如果我在 main
.
free()
,警告就会消失
在此先感谢您的帮助。请让我知道更多详细信息(例如警告的行号)是否有帮助。
与怀疑的一样,没有内存泄漏。
为了告诉 splint
哪个函数应该控制结构的内存,析构函数的输入应该用 /*@only@*/
注释。
static void Boring_destroy( /*@only@*/ struct Boring *really ) {...
这告诉 splint
该函数正在单独控制变量,从而允许它和平地释放内存而不会引发任何警告。
更具体地说,唯一的注释'indicate[s] a reference is the only pointer to the object it points to.'(夹板手册)
注释删除了原始问题中提到的两个警告,并将它们替换为指示 tv
在被销毁后正在使用的警告。这个新警告是可取的,因为正如 WhozCraig 在评论中提到的,一旦内存被释放就调用内存是未定义的行为,因此应该避免。
参考文献:
- SO questioin about splint and memory ownership
- splint manual(参见 5.2.1. 非共享引用)