尝试malloc时,特定输出出现Valgrind泄漏和分段错误
所以我有一个程序,它接收一个字符串作为输入,格式是尝试malloc时,特定输出出现Valgrind泄漏和分段错误,c,list,pointers,memory-leaks,valgrind,C,List,Pointers,Memory Leaks,Valgrind,所以我有一个程序,它接收一个字符串作为输入,格式是a word1 word2 word3,然后将这些单词插入到一个结构中,最后放入一个链表中。对于我尝试过的所有输入,它工作得很好,没有内存泄漏,但是对于这个特定的输出,我得到了一个分段错误以及内存泄漏,这几乎可以肯定是因为word1的长度。 这是输入: a 阿道夫•布莱恩•查尔斯•大卫•厄尔•弗雷德里克•杰拉尔德•休伯特•欧文•约翰•肯尼斯•劳埃德•马丁•尼禄•奥利弗•保罗•昆西•兰多夫•谢尔曼•托马斯•维克托•威廉•薛西斯•扬西•宙斯•沃尔夫斯
a word1 word2 word3
,然后将这些单词插入到一个结构中,最后放入一个链表中。对于我尝试过的所有输入,它工作得很好,没有内存泄漏,但是对于这个特定的输出,我得到了一个分段错误以及内存泄漏,这几乎可以肯定是因为word1
的长度。
这是输入:
a
阿道夫•布莱恩•查尔斯•大卫•厄尔•弗雷德里克•杰拉尔德•休伯特•欧文•约翰•肯尼斯•劳埃德•马丁•尼禄•奥利弗•保罗•昆西•兰多夫•谢尔曼•托马斯•维克托•威廉•薛西斯•扬西•宙斯•沃尔夫斯基•格尔斯泰因豪斯博格多夫•韦尔夫•韦尔切沃·沃尔夫韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦尔韦我们的研究者和研究者的研究者发现,在过去的一段时间里,我们发现了一种新的研究方法,这种方法可以使我们的研究人员更清楚地认识到这一点在过去的几年里,我们一直在寻找新的知识来源foo@bar.zp2.
这是我的密码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXINPUT 682
typedef struct words {
char *word1;
char *word2;
char *word3;
} words;
typedef struct node{
words cont;
struct node *next;
} node;
typedef node *link;
link head;
void add(char c[]) {
words x;
char *str;
link temp = (link)malloc(sizeof(node));
strtok(c, " ");
str = strtok(NULL, " ");
x.word1 = (char *)malloc(sizeof(char) * (strlen(str) + 1));
strcpy(x.word1, str);
str = strtok(NULL, " ");
x.word2 = (char *)malloc(sizeof(char) * (strlen(str) + 1)); /* where the error happens with this input */
strcpy(x.word2, str);
str = strtok(NULL, "\0");
x.word3 = (char *)malloc(sizeof(char) * (strlen(str) + 1));
strcpy(x.word3, str);
temp->cont = x;
temp->next = head;
head = temp;
}
int main() {
char input[MAXINPUT] = " ";
head = NULL;
while (input[0] != 'x') {
fgets(input, MAXINPUT, stdin);
input[strcspn(input, "\r\n")] = 0;
if (input[0] == 'a')
add(input);
...
#包括
#包括
#包括
#定义MAXINPUT 682
typedef结构字{
char*word1;
char*word2;
char*word3;
}文字;
类型定义结构节点{
单词cont;
结构节点*下一步;
}节点;
typedef节点*链接;
连杆头;
无效添加(字符c[]{
x字;
char*str;
链接温度=(链接)malloc(sizeof(节点));
斯特托克(c)(“”);
str=strtok(空,“”);
x、 word1=(char*)malloc(sizeof(char)*(strlen(str)+1));
strcpy(x.word1,str);
str=strtok(空,“”);
x、 word2=(char*)malloc(sizeof(char)*(strlen(str)+1));/*其中此输入发生错误*/
strcpy(x.word2,str);
str=strtok(空,“\0”);
x、 word3=(char*)malloc(sizeof(char)*(strlen(str)+1));
strcpy(x.word3,str);
温度->控制=x;
温度->下一步=头部;
压头=温度;
}
int main(){
字符输入[MAXINPUT]=“”;
head=NULL;
while(输入[0]!=“x”){
fgets(输入、最大输入、标准输入);
输入[strcspn(输入,“\r\n”)]=0;
如果(输入[0]=“a”)
添加(输入);
...
当我用这个代码运行这个输入时,我得到了一个分段错误,valgrind说有3个alloc,只有一个空闲,并且泄漏\错误发生在代码中提到的行中,特别是strlen。它还说我出于某种原因无法访问内存位置0x0。我想知道为什么会发生这种情况,而不是ks!您不测试strtok
是否找到了所有令牌。在使用它之前,您必须检查strtok()
返回的指针。如果不检查,无效输入将导致未定义的行为
在您的情况下,输入长度超过682个字节,前681个字节被读入数组,而此片段不包含足够的令牌,使得其中一个strok()
调用返回NULL
,当您使用strlen()
取消引用此空指针时,会导致未定义的行为
始终测试和报告错误情况,您将节省无数个小时的调试时间
当程序崩溃时,valgrind报告的内存泄漏是没有意义的,因为程序没有完成正常执行,当然也没有正确释放分配的内存。程序退出后,内存仍会返回操作系统,但valgrind报告调用free()未释放的块
为了避免对行长度设置任意限制,可以使用根据需要重新分配数组的
您还应该使用strdup
在单个函数调用中分配字符串的副本:
#包括
#包括
#包括
typedef结构字{
char*word1;
char*word2;
char*word3;
}文字;
类型定义结构节点{
单词cont;
结构节点*下一步;
}节点;
typedef node*link;//不建议在typedef后面隐藏指针
连杆头;
链接添加(字符c[]){
单词x={NULL,NULL,NULL};
char*str;
链路温度;
如果(strtok(c,“”)=NULL
&&(str=strtok(NULL,“”)!=NULL
&&(x.word1=strdup(str))!=NULL
&&(str=strtok(NULL,“”)!=NULL
&&(x.word2=strdup(str))!=NULL
&&(str=strtok(NULL,“”)!=NULL
&&(x.word3=strdup(str))!=NULL
&&(temp=malloc(sizeof(*temp))!=NULL){
温度->控制=x;
温度->下一步=头部;
回流头=温度;
}否则{
免费(x.3);
免费(x.2);
免费(x.1);
返回NULL;
}
}
int main(){
char*input=NULL;
大小输入大小=0;
head=NULL;
while(getline(&input,&input_size,stdin)>=0&&input!='x'){
输入[strcspn(输入,“\r\n”)]='\0';
如果(*输入=='a')
添加(输入);
...
}
...
}
免费(输入);
...
返回0;
}
OP迄今为止从未接受过答案……可能会建议OP使用ssize\u t getline(char**lineptr,size\u t*n,FILE*stream);
而不是FGET来消除限制?(使用valgrind,他可能使用符合POSIX的编译器)