存储错误的值和其他

时间:2013-04-01 11:22:49

标签: c linux linked-list segmentation-fault stack

我制作了这个节目:

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

谢谢

2 个答案:

答案 0 :(得分: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);

您正在向next的{​​{1}}分配新对象。然后覆盖它将list对象。然后删除tmp对象。所以tmp将是悬空指针

答案 1 :(得分:0)

此:

void addelem(llist *list,int val)
{

  ...

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

看起来很危险。

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

下次next被访问时,程序最有可能死亡。