如何为 Splint 注释 BoehmGC 收集的代码?

发布于 2024-11-27 18:16:11 字数 863 浏览 6 评论 0原文

Splint 可以很好地追踪 C 代码中的内存泄漏。每个malloc() 都应该有一个匹配的free()。但 BoehmGC 收集的代码使用 GC_MALLOC() 且没有匹配的 GC_FREE()。这使得 Splint 因大量实际上并不存在的内存泄漏消息而变得疯狂。

有谁知道此类代码的正确注释,以便 Splint 不再显示虚假的内存泄漏消息?

特别是,有人可以注释 维基百科 BoehmGC 示例吗?

#include <assert.h>
#include <stdio.h>
#include <gc.h>

int main(void)
{
    int i;

    GC_INIT();
    for (i = 0; i < 10000000; ++i)
    {
        int **p = GC_MALLOC(sizeof(int *));
        int *q = GC_MALLOC_ATOMIC(sizeof(int));

        assert(*p == 0);
        *p = GC_REALLOC(q, 2 * sizeof(int));
        if (i % 100000 == 0)
            printf("Heap size = %zu\n", GC_get_heap_size());
    }

    return 0;
}

Splint does a good job tracking down memory leaks in C code. Every malloc() should have a matching free(). But BoehmGC-collected code uses GC_MALLOC() with no matching GC_FREE(). This makes Splint go crazy with tons of messages about memory leaks that aren't actually there.

Does anyone know the proper annotation for such code so that Splint no longer shows spurious memory leak messages?

In particular, could someone annotate Wikipedia's BoehmGC example?

#include <assert.h>
#include <stdio.h>
#include <gc.h>

int main(void)
{
    int i;

    GC_INIT();
    for (i = 0; i < 10000000; ++i)
    {
        int **p = GC_MALLOC(sizeof(int *));
        int *q = GC_MALLOC_ATOMIC(sizeof(int));

        assert(*p == 0);
        *p = GC_REALLOC(q, 2 * sizeof(int));
        if (i % 100000 == 0)
            printf("Heap size = %zu\n", GC_get_heap_size());
    }

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风吹雨成花 2024-12-04 18:16:11

我认为您应该注释BoehmGC API 本身,然后示例所需的注释(如果有)就会变得明显。

对于初学者来说,没有注释的函数返回的任何指针都是隐式@only,这意味着您必须在引用丢失之前释放关联的内存。因此,第一步是注释分配器,以便它们不再返回 @only 引用。相反,手册建议使用共享引用

如果 Splint 用于检查设计用于
垃圾收集环境中,可能存在共享的存储
一个或多个参考文献,但从未明确发布过。所共享的
注解声明可以任意共享的存储,但决不能
已发布。

如果您不想修改 BoehmGC API,您可以通过创建正确注释的包装函数来解决它。此外,您需要在包装函数中禁用特定的传输错误(因为它们从 BoehmGC API 获取隐式 @only 引用,然后将其返回为 @共享)。

例如,这是您在代码的给定点禁用“语句无效”错误的方法:

/*@-noeffectuncon@*/
not_annotated_void_function();
/*@=noeffectuncon@*/

包装函数将如下所示:

/*@shared@*/ /*@null@*/ /*@out@*/ static void * MY_GC_MALLOC(size_t size) /*@*/{
    /*@-onlytrans@*/
    return( GC_MALLOC(size) );
    /*@=onlytrans@*/
}

然后在示例中您将使用MY_GC_MALLOC 而不是 GC_MALLOC

I think that you should annotate the BoehmGC API itself, and then the annotations needed for the example (if any) will become obvious.

For starters, any pointer returned by a function with no annotation is implicitly @only, which means that you must release the associated memory before reference is lost. Therefore, the first step would be to annotate the allocators so that they no longer return an @only reference. Instead, the manual advises using shared references:

If Splint is used to check a program designed to be used in a
garbage-collected environment, there may be storage that is shared by
one or more references and never explicitly released. The shared
annotation declares storage that may be shared arbitrarily, but never
released.

If you didn't want to modify the BoehmGC API, you could work around it by creating properly annotated, wrapper functions. In addition, you would need to disable specific transfer errors within your wrapper functions (because they get an implicit @only reference from the BoehmGC API and then return it as @shared).

For example, this is the way you would disable the "Statement has no effect" error at a given point of your code:

/*@-noeffectuncon@*/
not_annotated_void_function();
/*@=noeffectuncon@*/

The wrapper function would be something like this:

/*@shared@*/ /*@null@*/ /*@out@*/ static void * MY_GC_MALLOC(size_t size) /*@*/{
    /*@-onlytrans@*/
    return( GC_MALLOC(size) );
    /*@=onlytrans@*/
}

Then in the example you'd use MY_GC_MALLOC rather than GC_MALLOC.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文