在c中的驱逐舰功能中使用free()后的内存泄漏(根据夹板)

时间:2015-06-26 15:51:01

标签: c memory splint

我正在重新学习C,并使用splint来测试我的源代码。

我正在尝试执行以下操作:

  • 使用"构造函数"创建一个结构功能
  • 使用"析构函数"销毁结构。函数,释放结构的记忆。

但是,当我使用splint测试我的代码时,它会在析构函数中发出与临时存储相关的警告,并在调用析构函数后发生内存泄漏。

我想知道(a)我的代码中是否有关于内存泄漏的夹板(我认为不是),以及(b)我应该做些什么来修复我的代码或让夹板理解我在做什么。

无论如何,这是代码:

#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会发出以下警告:

$> 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

第一个警告,我想的越多,我理解的就越少。但我还没有阅读足够的手册来证明有关该手册的正确问题。

关于内存泄漏的第二个警告,似乎夹板只是没有意识到内存在其他地方被释放,这对我来说似乎很奇怪。如果我只是在free()内拨打main,警告就会消失。

提前感谢您的帮助。如果有更多详细信息(如警告的行号)会有帮助,请告诉我。

1 个答案:

答案 0 :(得分:3)

怀疑没有内存泄漏。

为了告诉splint哪个函数应该控制结构的内存,析构函数的输入应该用/*@only@*/注释。

static void Boring_destroy( /*@only@*/ struct Boring *really ) {...

这告诉splint该函数正在单独控制变量,从而允许它在不引发任何警告的情况下安静地释放内存。

更具体地说,唯一的注释&#39;表示[s]引用是指向它指向的对象的唯一指针。&#39; (夹板手册)

注释会删除原始问题中提到的警告,并将其替换为警告,指示tv在被销毁后正在使用。这个新的警告是可取的,因为正如WhozCraig在评论中提到的那样,一旦被释放就调用内存是未定义的行为,因此应该避免。

参考文献: