使用 malloc 字符串的 C 分段错误
C segmentation fault using malloc'ed strings
本质上,我的代码中有一个链表结构,
struct node{
char* val;
struct node *next;
};
然后我尝试对它做一些事情...
...
addr = malloc(sizeof(struct node));
addr->val = malloc(72);
addr->val = "";
snprintf(addr->val, 1000, "%s", ident);
...
...
这给了我 snprintf 的分段错误。 Valgrind 表示如下
Process terminating with default action of signal 11 (SIGSEGV)
==10724== Bad permissions for mapped region at address 0x40566B
==10724== at 0x4EB0A32: vsnprintf (vsnprintf.c:112)
==10724== by 0x4E8F931: snprintf (snprintf.c:33)
==10724== by 0x4016CC: id (Analyzer.c:267)
...
与 C++ 相比,我对 C 还很陌生,但我认为在 char* 上调用 malloc 应该使它有效,特别是因为我可以初始化和打印它,所以我不明白为什么 snprintf 不会工作。
我还让我的程序打印出两个变量的地址,而 valgrind 抱怨的地址确实来自 addr->val.
我也尝试过使用 strcpy 而不是 snprintf,但结果相同。
谢谢。
代码
addr->val = malloc(72);
addr->val = ""; <====
用“”覆盖val
指针,静态区域的地址,由 1 个字符(值为 0)组成。删除此行。
和
snprintf(addr->val, 1000, "%s", ident);
接受 1000 的长度,而您只分配了 72 个字符。
snprintf(addr->val, 72, "%s", ident);
更好。
addr->val = malloc(72);
这一行动态分配了72个字节并将该内存区域的地址分配给addr->val
。
addr->val = "";
然后将 addr->val
设置为指向字符串常量的地址,丢弃其先前包含的分配内存区域的地址,从而导致内存泄漏。
当您随后尝试使用 snprintf
时,您正在尝试写入字符串文字。由于这些通常存储在内存的只读部分,因此尝试这样做会导致核心转储。
不需要addr->val = "";
。它丢弃分配的内存;它不会将分配的内存设置为空字符串,这可能是您认为它会做的。即使这样做了,也无济于事,因为 snprintf
会覆盖可能存在的任何内容。
addr->val = malloc(72);
addr->val = "";
第二行将addr->val
重新分配给只读段(字符串文字所在的地址)的地址,并丢弃malloc
分配的地址,这可能会导致潜在的内存泄漏。
我知道你想清除它。要分配字符串,您应该使用 strcpy()
strcpy(addr->val, "");
但是既然要清空它,最简单的方法就是将第一个字符设置为零:
addr->val[0] = '[=12=]';
此外,您正试图从事一项可能有害的工作:
snprintf(addr->val, 1000, "%s", ident);
你打算分配72个字节,但为什么我们的第二个参数增加到1k?将其更改为更安全的号码:
snprintf(addr->val, 72, "%s", ident);
到时候应该一切都好。
本质上,我的代码中有一个链表结构,
struct node{
char* val;
struct node *next;
};
然后我尝试对它做一些事情...
...
addr = malloc(sizeof(struct node));
addr->val = malloc(72);
addr->val = "";
snprintf(addr->val, 1000, "%s", ident);
...
... 这给了我 snprintf 的分段错误。 Valgrind 表示如下
Process terminating with default action of signal 11 (SIGSEGV)
==10724== Bad permissions for mapped region at address 0x40566B
==10724== at 0x4EB0A32: vsnprintf (vsnprintf.c:112)
==10724== by 0x4E8F931: snprintf (snprintf.c:33)
==10724== by 0x4016CC: id (Analyzer.c:267)
...
与 C++ 相比,我对 C 还很陌生,但我认为在 char* 上调用 malloc 应该使它有效,特别是因为我可以初始化和打印它,所以我不明白为什么 snprintf 不会工作。 我还让我的程序打印出两个变量的地址,而 valgrind 抱怨的地址确实来自 addr->val.
我也尝试过使用 strcpy 而不是 snprintf,但结果相同。
谢谢。
代码
addr->val = malloc(72);
addr->val = ""; <====
用“”覆盖val
指针,静态区域的地址,由 1 个字符(值为 0)组成。删除此行。
和
snprintf(addr->val, 1000, "%s", ident);
接受 1000 的长度,而您只分配了 72 个字符。
snprintf(addr->val, 72, "%s", ident);
更好。
addr->val = malloc(72);
这一行动态分配了72个字节并将该内存区域的地址分配给addr->val
。
addr->val = "";
然后将 addr->val
设置为指向字符串常量的地址,丢弃其先前包含的分配内存区域的地址,从而导致内存泄漏。
当您随后尝试使用 snprintf
时,您正在尝试写入字符串文字。由于这些通常存储在内存的只读部分,因此尝试这样做会导致核心转储。
不需要addr->val = "";
。它丢弃分配的内存;它不会将分配的内存设置为空字符串,这可能是您认为它会做的。即使这样做了,也无济于事,因为 snprintf
会覆盖可能存在的任何内容。
addr->val = malloc(72);
addr->val = "";
第二行将addr->val
重新分配给只读段(字符串文字所在的地址)的地址,并丢弃malloc
分配的地址,这可能会导致潜在的内存泄漏。
我知道你想清除它。要分配字符串,您应该使用 strcpy()
strcpy(addr->val, "");
但是既然要清空它,最简单的方法就是将第一个字符设置为零:
addr->val[0] = '[=12=]';
此外,您正试图从事一项可能有害的工作:
snprintf(addr->val, 1000, "%s", ident);
你打算分配72个字节,但为什么我们的第二个参数增加到1k?将其更改为更安全的号码:
snprintf(addr->val, 72, "%s", ident);
到时候应该一切都好。