尝试访问功能时出现分段错误

时间:2019-03-07 17:18:50

标签: c pointers linked-list segmentation-fault

我相信细分错误是在我的If语句上发生的,但是我不确定为什么,当使用测试时,即使测试knapsack == NULL时它甚至都没有进入if语句,下一个printf语句。即使我的主设备将NULL传递给背包,我是否也不能测试背包是否等于NULL?根据规格,只能编辑Knapsack.c。 Knapsack.h和Knapsack-testcase1.c已提供给我,并被明确告知不要进行编辑。

Knapsack.h

/* knapsack.h
 * implements simple knapsack data structure as a linked list 
 * NOTE: a function may update the value of input argument *knapsack if it changes the first node of the knapsack to another node. Such a change include the case when an item is added to an empty knapsack
 */

typedef struct listitem* listitemptr;

struct listitem {
  int item;           // actual int item
  unsigned int count; // number of the same item in the knapsack; should be >= 1
  listitemptr next;   // pointer to next item 
};

listitemptr KnapsackAdd(listitemptr *knapsack, int item);    
int KnapsackRemove(listitemptr *knapsack, int item);
void KnapsackPrint(const listitemptr *knapsack);
unsigned int KnapsackItemCount(const listitemptr *knapsack, int item);
unsigned int KnapsackSize(const listitemptr *knapsack);

Knapsack.c

#include "knapsack.h"
#include <stdio.h>
#include <stdlib.h>

listitemptr KnapsackAdd(listitemptr *knapsack, int item){
   if(*knapsack==NULL){//empty list
       listitemptr newest= (listitemptr) malloc(sizeof(struct listitem));
       newest->item=item;
       newest->count=1;
       newest->next=NULL;
       return newest;
   }else{
       listitemptr temp=*knapsack;
       listitemptr previous=NULL;
       while(temp!=NULL){
           if(temp->item == item){
               temp->count=temp->count+1;
               break;
           }
           previous=temp;
           temp=temp->next;
       }
       if(temp==NULL){
           listitemptr newest= (listitemptr) malloc(sizeof(struct listitem));
           newest->item=item;
           newest->count=1;
           newest->next=NULL;
           previous->next=newest;
           return newest;
       }
       return temp;
   }
}

int KnapsackRemove(listitemptr *knapsack, int item){
   if(*knapsack==NULL)
       return -1;
   listitemptr present=*knapsack;
   listitemptr previous=NULL;

   while(present!=NULL){
       if(present->item==item){
           if(present->count>1){
               present->count=present->count-1;
           }else{
               if(previous==NULL){ //delete at head
                   *knapsack=present->next;
               }else{
                   previous->next=present->next;
                   free(present);
               }
           }
           break;
       }
       previous=present;
       present=present->next;
   }

   return 0;
}

void KnapsackPrint(const listitemptr *knapsack){
   if(*knapsack==NULL)
       printf("(nothing)\n");
   else{
       listitemptr temp=*knapsack;
       while(temp!=NULL){
           printf("%d (%d), ",temp->item,temp->count);
           temp=temp->next;
       }
       printf("\n");
   }
}

unsigned int KnapsackItemCount(const listitemptr *knapsack, int item){
   if(*knapsack==NULL)
       return 0;
   listitemptr temp=*knapsack;
   while(temp!=NULL){
       if(temp->item==item)
           return temp->count;
       temp=temp->next;
   }
   return 0;  
}

unsigned int KnapsackSize(const listitemptr *knapsack){
    printf("saada\n");
   if(*knapsack==NULL){
    printf("testing\n");
       return 0;
   }

   listitemptr temp=*knapsack;
   unsigned int sum=0;
   while(temp!=NULL){
       sum+=temp->count;
       temp=temp->next;
   }
   return sum;

背包测试箱1.c

#include <stdio.h>
#include <assert.h>

#include "knapsack.h"

int main(int argc, char* *argv){
    listitemptr k1 = NULL;
    int returnval;

    printf("Test case 1\n");

    printf("Asserting empty knapsack has size 0\n");
    returnval = KnapsackSize(&k1);
    assert(returnval == 0);

    KnapsackAdd(&k1, 1);
    printf("Asserting knapsack with one item (count 1) has size 1\n");
    returnval = KnapsackSize(&k1);
    assert(returnval == 1);

    printf("Test passed\n");
return 0;
}

1 个答案:

答案 0 :(得分:1)

没有分段错误,但是有一个断言失败,即测试用例中的最后一个。发生这种情况的原因是因为k1NULL,这是因为在KnapsackAdd()中第一个if测试命中,并且分配并初始化了一个新的listitemptr。但是,然后返回此值,并且该返回值未包含在测试用例中,这意味着k1永远不会设置为新的listitemptr。这既是内存泄漏,也是逻辑错误。

为了修复它,最简单的方法是将knapsack参数设置为指向指针的指针,然后将其设置为KnapsackAdd()中新分配的项。< / p>