![](/img/trans.png)
[英]MSVC casts pointers from any type to any type implicitly in .c files, not giving errors or warnings. Why?
[英]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.