释放时填充结构数据会导致段错误
populating struct data causes a segfault when freed
我有一些创建新结构(包含字符串和长度)并删除该结构的简单代码。
/* string/proc.c */
#include "proc.h" /* String */
#include <malloc.h>
#include <assert.h>
#include <stddef.h> /* NULL */
struct string {
char* str;
int len;
};
String new_string (int length)
{
String S;
S = (String) malloc (sizeof (String));
S ->str = (char*) malloc (sizeof (char*) * length + 1);
S ->str [length] = '[=10=]';
S ->len = length;
return S;
}
void delete_string (String *Sp)
{
free ((*Sp) ->str);
free (*Sp);
*Sp = NULL;
}
/* end of file */
这些函数是通过头文件公开的,结构是 typedef 的。
/* string/proc.h */
#ifndef string_proc_h
#define string_proc_h
typedef struct string* String;
String new_string (int length);
void delete_string (String*);
#endif
/* end of file */
我还有一个测试文件,其中#include 那个头文件并测试新函数和删除函数:
/* string/proc_test.c */
#include "proc.h"
#include <assert.h>
#include <stddef.h> /* NULL */
int test_new_string ()
{
int ok = 0;
String S = new_string (10);
assert (S);
ok ++;
delete_string (&S);
return ok;
}
int test_delete_string ()
{
int ok = 0;
String S = new_string (10);
delete_string (&S);
assert (S == NULL);
ok ++;
return ok;
}
/* end of file */
问题:当我 运行 这个程序时,我遇到了分段错误(核心已转储)。
我可以使用 dbg 将其跟踪到 proc.c 文件的这一行:
*Sp = NULL;
但是:
当我从 proc.c 文件中删除 这 行时:
S ->len = length;
...两个测试都完美通过!
为什么程序运行良好,通过了测试,但是当我尝试更改范围内的结构时,它导致我的代码中看似无关的部分出现段错误?
我看不出它们有什么关系...你能帮我吗?
线条
S = (String) malloc (sizeof (String));
S ->str = (char*) malloc (sizeof (char*) * length + 1);
错了。应该是:
S = malloc (sizeof (*S));
S ->str = malloc (sizeof (*(S->str)) * length + 1);
或
S = malloc (sizeof (struct string));
S ->str = malloc (sizeof (char) * length + 1);
第一行是致命的。它只分配一个指针,而需要分配结构。第二行不是致命的,但它会分配一些额外的内存,因为它为每个元素分配一个指针,而只需要一个字符的空间。
另请注意,malloc()
家族的铸造结果是 considered as a bad practice。
另一个建议是你不应该使用 typedef
来隐藏这样的指针,因为它会使它更混乱。
我有一些创建新结构(包含字符串和长度)并删除该结构的简单代码。
/* string/proc.c */
#include "proc.h" /* String */
#include <malloc.h>
#include <assert.h>
#include <stddef.h> /* NULL */
struct string {
char* str;
int len;
};
String new_string (int length)
{
String S;
S = (String) malloc (sizeof (String));
S ->str = (char*) malloc (sizeof (char*) * length + 1);
S ->str [length] = '[=10=]';
S ->len = length;
return S;
}
void delete_string (String *Sp)
{
free ((*Sp) ->str);
free (*Sp);
*Sp = NULL;
}
/* end of file */
这些函数是通过头文件公开的,结构是 typedef 的。
/* string/proc.h */
#ifndef string_proc_h
#define string_proc_h
typedef struct string* String;
String new_string (int length);
void delete_string (String*);
#endif
/* end of file */
我还有一个测试文件,其中#include 那个头文件并测试新函数和删除函数:
/* string/proc_test.c */
#include "proc.h"
#include <assert.h>
#include <stddef.h> /* NULL */
int test_new_string ()
{
int ok = 0;
String S = new_string (10);
assert (S);
ok ++;
delete_string (&S);
return ok;
}
int test_delete_string ()
{
int ok = 0;
String S = new_string (10);
delete_string (&S);
assert (S == NULL);
ok ++;
return ok;
}
/* end of file */
问题:当我 运行 这个程序时,我遇到了分段错误(核心已转储)。
我可以使用 dbg 将其跟踪到 proc.c 文件的这一行:
*Sp = NULL;
但是:
当我从 proc.c 文件中删除 这 行时:
S ->len = length;
...两个测试都完美通过!
为什么程序运行良好,通过了测试,但是当我尝试更改范围内的结构时,它导致我的代码中看似无关的部分出现段错误?
我看不出它们有什么关系...你能帮我吗?
线条
S = (String) malloc (sizeof (String));
S ->str = (char*) malloc (sizeof (char*) * length + 1);
错了。应该是:
S = malloc (sizeof (*S));
S ->str = malloc (sizeof (*(S->str)) * length + 1);
或
S = malloc (sizeof (struct string));
S ->str = malloc (sizeof (char) * length + 1);
第一行是致命的。它只分配一个指针,而需要分配结构。第二行不是致命的,但它会分配一些额外的内存,因为它为每个元素分配一个指针,而只需要一个字符的空间。
另请注意,malloc()
家族的铸造结果是 considered as a bad practice。
另一个建议是你不应该使用 typedef
来隐藏这样的指针,因为它会使它更混乱。