2013-04-01 67 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模具。