繁体   English   中英

C:夹板指针相关的警告。 什么意思

[英]C : Splint pointers related warnings. What does they mean?

以下代码编译并执行,没有任何警告或错误。 但是,当我使用夹板分析代码时,它会显示4条警告(显示在代码下方)。

我看到的大多数示例(带有这种警告)都使用malloc和free。 由于此代码不使用malloc,因此我们可以说忽略那些警告是安全的吗? 在不删除指针的情况下进行编码的正确方法是什么?

#include <stdio.h>

typedef struct
{
    void (*Doit) ( void );
} func;

typedef struct
{
    func f;
    int val;
} obj;

typedef struct
{
    obj *o;
} world;

static void Read( void ) {
    printf( "Read\n");
}

static void Init( world *w ) {
    obj pc;
    w->o = &pc;           //(1)
    w->o->val = 10;
    w->o->f.Doit = Read;
    w->o->f.Doit();
}

int main() {
    world w;
    Init( &w );     //(2)
    return 0;      //(3)
}

(1):28:5:隐式仅分配w-> o(类型obj *)的存储在分配前不释放:w-> o =&pc。 检测到内存泄漏。 在最后一次引用丢失之前,不会释放仅合格的存储。

(1):28:5:立即地址&pc仅隐式分配给:w-> o =&pc。 立即地址(&运算符的结果)传输不一致。

(2):33:11:定义之前使用的变量w使用的rvalue可能未初始化为某些执行路径上的值。

(3):34:14:仅释放从此作用域中声明的变量派生的存储器wo(类型obj *)(内存泄漏)。 怀疑由于结构或深度指针的不完全释放而导致的存储泄漏。 从正在释放的引用可以访问的未共享存储尚未释放。 Splint假定当一个对象作为唯一的void指针传递时,将释放外部对象,而不会释放内部对象。

这段代码只是对我想要实现的目标的测试,但是由于我不精通C语言,因此我想了解使用上述方法进行内存泄漏的风险。

提前致谢。

我发现splint输出非常不可读。 根据您的平台,您可能还需要尝试valgrind

无论如何,代码的主要问题是pc是局部变量。 它在Init()的末尾变得无效,因为它(可能与每个编译器一样)位于堆栈上。

您可能会想做

w->o = (obj *) malloc(sizeof(obj));

代替。

另一种执行此操作的方法是将w中o的类型更改为obj而不是obj *

有关C内存管理的注意事项 (强烈建议进一步阅读):

函数参数和局部变量通常位于所谓的stack 函数返回后,它们将立即失效。 堆栈对象的大小始终需要编译器知道。

通过malloc()分配的对象位于堆上。 malloc()可用于未知大小的对象。 malloc()分配的对象保持有效,直到将其指针传递给realloc()free()为止。 如果忘记将malloc的指针传递给free ,则会发生内存泄漏。 如果在对象变成无效对象后对其进行访问,您将得到未定义的行为(堆中的该位置现在可能已被其他东西重新使用,但是也许数据仍然存在,谁知道?)。 在最坏的情况下,您可能会遇到分段错误或堆损坏。 如果将无效的对象指针传递给free()realloc() ,则可能会导致堆损坏。

全局变量和静态函数成员位于其他地方(tm),并且在程序的整个执行过程中有效(至少从输入main到从main返回,就像main的局部变量一样)。

malloc()是一个复杂的函数,可在内部管理称为堆的复杂数据结构中的可用内存块。 堆损坏意味着您破坏了该数据结构本身。 分段错误意味着您在有效内存块之外的某处写入/读取。

请注意, C标准对此不做任何保证。 它不能保证甚至存在类似堆栈的东西。 但是,我所知道的所有编译器都这样做。 但是对于某些嵌入式平台, malloc()是一个非常简单的函数,每次分配某些内容时,它只会增加一个指针,而free()则什么也不做。

在Init()中

static void Init( world *w ) {
    obj pc;
    w->o = &pc;           //(1)
    w->o->val = 10;
    w->o->f.Doit = Read;
    w->o->f.Doit();
}

obj pc; 是函数Init()中的一个自动变量。

从Init()重新调整后,它指向的内存将无效。 因此,在main()中,Init()之后w-> o将无效。

你有使用malloc

w->o = (obj *) malloc(sizeof(obj)); 

您可以在Init()或main()中执行此操作。

注意:您必须使用free()释放它,否则会发生内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM