2013-04-01 74 views
-3

我在此程序:
错误值存储和其他

LLIST:

typedef struct linked_list 
    { 
     int val; 
     int n; 
     struct linked_list *next; 
    }llist; 

addelem功能:

void addelem(llist *list,int val) 
{ 
    llist *tmp=(llist *)malloc(sizeof(llist)); //create new element 
    tmp->val=val; //assign value to tmp 
    tmp->next=NULL; //set next to NULL 
    // printf("addelem entered\n"); 
    if(list->next!=NULL) //if this is not the last element 
    { 
     addelem(list->next,val); //recursion 
    } 
    else 
    { 
    tmp->n=list->n + 1; 
    list->next=(llist *)malloc(sizeof(llist)); //allocate memory 
    list->next=tmp; //add to list 
    } 
// printf("addelem exited\n"); 
    free(tmp); 
} 

remelem功能:

void remelem(llist *list) 
{ 
    int f=0; 
    if(list->n==0 && list->next==NULL) 
     goto dontremove; 
    if(1) 
    { 
    if(list->next!=NULL) 
    { 
     if(list->next->next==NULL) 
     { 
      f=1; 
     } 
     remelem(list->next); 
    } 
    else 
    { 
     free(list); 
    } 
    if(f==1) 
    { 
     list->next=NULL; 
    } 
    } 
    else 
    { 
dontremove: 
    printf("cant be removed even if the next message is 'Element removed.'\n"); 
    } 
    //end 
} 

放映功能:

void show(llist *list) 
{ 
    printf("Element number: %d\nElement Value: %d\n",list->n,list->val); 
    if(list->next!=NULL) 
    { 
     show(list->next); 
    } 
    else 
    { 
     printf("\nTotal number of elems: %d\n",list->n);; 
    } 
} 

主要功能:

int main() 
{ 
    int i,n,ch; 
    llist *list=(llist *)malloc(sizeof(llist)); 
    list->next=NULL; 
    list->n=0; 
    list->val=0; 
menu: //menu label 
    printf("1.Add element.\n"); 
    printf("2.Remove element.\n3.Show elements\n0.Exit.\n"); 
    scanf("%d",&ch); 
    switch(ch) 
    { 
     case 1: 
      printf("\nEnter value.\n"); 
      scanf("%d",&n); 
      addelem(list,n); 
      printf("Element added\n"); 
      break; 
     case 2: 
      remelem(list); 
      printf("\nElement removed.\n"); 
      break; 
     case 3: 
      show(list); 
      break; 
     case 0: 
      goto end; //end 
      break; 
    } 
    goto menu; //show menu again 
end: //end label 
    return 0; 
} 

输出:

1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
1 

Enter value. 
22 
Element added 
1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
1 

Enter value. 
4 
Element added 
1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
2 

Element removed. 
1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
3 
Element number: 0 
Element Value: 0 
Element number: 1 
Element Value: 161701936 

Total number of elems: 1 

的值是从邻不同我输入了。 我的第一个问题是,为什么会发生这种情况?(可能是一个愚蠢的错误),我如何修复它打印正确的值。



,这里是另一个输出:

1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
1 

Enter value. 
22 
Element added 
1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
1 

Enter value. 
23 
Element added 
1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
2 

Element removed. 
1.Add element. 
2.Remove element. 
3.Show elements 
0.Exit. 
1 

Enter value. 
22 
Segmentation fault (core dumped) 

在此,我首先添加元素,然后我删除它,但如果我再添加的元素,我得到分段错误,谁能解释为什么会发生这种情况,以及如何解决它?

如果起初我添加的元素,我删除它,然后这是我得到什么:

*** glibc detected *** ./llist: double free or corruption (fasttop): 0x0855b018 *** 

======= Backtrace: ========= 
certain memory addresses 
======= Memory map: ======== 
08048000-08049000 r-xp 00000000 08:01 1969473 /path/to/this/prog 
08049000-0804a000 r--p 00000000 08:01 1969473 /path/to/this/prog 
0804a000-0804b000 rw-p 00001000 08:01 1969473 /path/to/this/prog 
0855b000-0857c000 rw-p 00000000 00:00 0   [heap] 
b758e000-b75aa000 r-xp 00000000 08:01 3802036 /lib/i386-linux-gnu/libgcc_s.so.1 
b75aa000-b75ab000 r--p 0001b000 08:01 3802036 /lib/i386-linux-gnu/libgcc_s.so.1 
b75ab000-b75ac000 rw-p 0001c000 08:01 3802036 /lib/i386-linux-gnu/libgcc_s.so.1 
b75c3000-b75c4000 rw-p 00000000 00:00 0 
b75c4000-b7767000 r-xp 00000000 08:01 3805265 /lib/i386-linux-gnu/libc-2.15.so 
b7767000-b7768000 ---p 001a3000 08:01 3805265 /lib/i386-linux-gnu/libc-2.15.so 
b7768000-b776a000 r--p 001a3000 08:01 3805265 /lib/i386-linux-gnu/libc-2.15.so 
b776a000-b776b000 rw-p 001a5000 08:01 3805265 /lib/i386-linux-gnu/libc-2.15.so 
b776b000-b776e000 rw-p 00000000 00:00 0 
b7782000-b7787000 rw-p 00000000 00:00 0 
b7787000-b7788000 r-xp 00000000 00:00 0   [vdso] 
b7788000-b77a8000 r-xp 00000000 08:01 3805277 /lib/i386-linux-gnu/ld-2.15.so 
b77a8000-b77a9000 r--p 0001f000 08:01 3805277 /lib/i386-linux-gnu/ld-2.15.so 
b77a9000-b77aa000 rw-p 00020000 08:01 3805277 /lib/i386-linux-gnu/ld-2.15.so 
bf969000-bf98a000 rw-p 00000000 00:00 0   [stack] 
Aborted (core dumped) 

谁能告诉为什么这些错误已经发生?

我使用Ubuntu 12.04

谢谢

+0

woho,那真的很长。 –

+1

您可能会考虑使用valgrind运行您的程序。它会指出你一些讨厌的问题。 – alk

+0

使用'goto'总是引发讨论。我有时会以结构化的方式使用它们,以便轻松地实现函数的出口点而不会扰乱源。但这个'do​​ntremove'真的很难看。 – alk

回答

1

你的功能addelem包含了很多错误。检查我的代码

void addelem(llist *list,int val) 
{ 
    llist *tmp=malloc(sizeof(llist)); //create new element 
    tmp->val=val; //assign value to tmp 
    tmp->next=NULL; //set next to NULL 
    // printf("addelem entered\n"); 
    if(list->next!=NULL) //if this is not the last element 
    { 
     addelem(list->next,val); //recursion 
     free(tmp); //not using tmp in this function 
    } 
    else 
    { 
     tmp->n = list->n + 1; 
     list->next=tmp; 
    } 
} 

在下面的语句ypir代码包含很多错误

else 
{ 
tmp->n=list->n + 1; 
list->next=malloc(sizeof(llist)); //allocate memory 
list->next=tmp; //add to list 
} 
// printf("addelem exited\n"); 
free(tmp); 

您assinging新对象的listnext。然后覆盖它将tmp对象。然后删除tmp对象。所以list->next将悬摆指针

+0

你能解释一下变量'parser'是做什么的,头怎么会是NULL,因为我指向了堆栈的第一个元素,它不是NULL? –

+0

o是的。您正在初始化第一个节点@main并且不删除它。所以不需要用NULL来检查头部。而不是递归函数我正在使用while循环与解析器来解析列表直到结束添加新元素 – 999k

+0

我将用无代码循环代码 – 999k

0

此:

void addelem(llist *list,int val) 
{ 

    ... 

    list->next=tmp; //add to list 
    } 
    // printf("addelem exited\n"); 
    free(tmp); 
} 

看起来致命的危险。

首先,您将tmp分配给列表的next成员,然后您可以释放它指向的内容。

下一次next被访问的程序最likley模具。