使用Valgrind在C中无效读取大小8的分段错误

马特克

我正在为一个学校项目编写一个程序,该程序使用A *搜索来遍历可能的状态列表并选择下一个最佳状态以进行解决。

我想清楚一点,我不是要寻找家庭作业的解决方案,而是要解决这些错误。我在网上查看了许多其他问题,发现在某个时候地址0x0意味着我正在尝试访问NULL,因为该内存不再存在。我不知道我的程序在哪里发生或如何发生。

我遇到了一些错误,这些错误似乎无法跟踪或理解在程序上使用gdb和valgrind。

有人可以看看这些错误和我的代码,也许可以弄清楚为什么程序会出现段错误?我在这部分上停留了很长时间。

运行Valgrind的结果:

==80117== Invalid read of size 8
==80117==    at 0x4011AB: freeList (AST.c:403)

==80117==    by 0x401E24: main (main.c:129)
==80117==  Address 0x51a8dd8 is 24 bytes inside a block of size 32 free'd
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x400E58: removeFringe (AST.c:267)
==80117==    by 0x401DB4: main (main.c:104)
==80117==
==80117== Invalid read of size 8
==80117==    at 0x4011B7: freeList (AST.c:404)
==80117==    by 0x401E24: main (main.c:129)
==80117==  Address 0x51a8dc0 is 0 bytes inside a block of size 32 free'd
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x400E58: removeFringe (AST.c:267)
==80117==    by 0x401DB4: main (main.c:104)
==80117==
==80117== Invalid read of size 8
==80117==    at 0x401511: freeDiscs (discs.c:140)
==80117==    by 0x4011C1: freeList (AST.c:404)
==80117==    by 0x401E24: main (main.c:129)
==80117==  Address 0x51a8e30 is 16 bytes inside a block of size 24 free'd
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x401521: freeDiscs (discs.c:141)
==80117==    by 0x400E4F: removeFringe (AST.c:266)
==80117==    by 0x401DB4: main (main.c:104)
==80117==
==80117== Invalid free() / delete / delete[] / realloc()
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x401521: freeDiscs (discs.c:141)
==80117==    by 0x4011C1: freeList (AST.c:404)
==80117==    by 0x401E24: main (main.c:129)
==80117==  Address 0x51a8e20 is 0 bytes inside a block of size 24 free'd
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x401521: freeDiscs (discs.c:141)
==80117==    by 0x400E4F: removeFringe (AST.c:266)
==80117==    by 0x401DB4: main (main.c:104)
==80117==
==80117== Invalid free() / delete / delete[] / realloc()
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x4011CA: freeList (AST.c:405)
==80117==    by 0x401E24: main (main.c:129)
==80117==  Address 0x51a8dc0 is 0 bytes inside a block of size 32 free'd
==80117==    at 0x4C2701C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==80117==    by 0x400E58: removeFringe (AST.c:267)
==80117==    by 0x401DB4: main (main.c:104)
==80117==
==80117==
==80117== HEAP SUMMARY:
==80117==     in use at exit: 0 bytes in 0 blocks
==80117==   total heap usage: 128 allocs, 134 frees, 3,112 bytes allocated
==80117==
==80117== All heap blocks were freed -- no leaks are possible
==80117==
==80117== For counts of detected and suppressed errors, rerun with: -v
==80117== ERROR SUMMARY: 13 errors from 5 contexts (suppressed: 4 from 4)

运行GDB的结果:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401511 in freeDiscs (discs=0x0, MAX_SLOTS=5) at discs.c:140
140         discs = discs->next;
(gdb) backtrace
#0  0x0000000000401511 in freeDiscs (discs=0x0, MAX_SLOTS=5) at discs.c:140
#1  0x00000000004011c2 in freeList (list=0x604220, MAX_SLOTS=5) at AST.c:404
#2  0x0000000000401e25 in main (argc=2, argv=0x7fffffffe048) at main.c:129
(gdb)

从边缘移除状态相同的多个节点的函数:

/* removes nodes from the fringe and then returns the fringe */
struct AST_Node * removeFringe(struct AST_Node * fringe, struct AST_Node * remove, int MAX_SLOTS) {
  struct AST_Node * head, * current, * prev, * delete;
  int remove_switch = 0;
  head = fringe;
  current = fringe;
  prev = fringe;

  /* traverse the fringe until the end */
  while (current != NULL) {
    /* when the current node has the same state as the one for removal */
    if (isSame(current->state, remove->state, MAX_SLOTS)) {
      /* when removing from the head */
      if (current == head) {
        head = current->parent;
        delete = current;
        current = head;
        freeDiscs(delete->state, MAX_SLOTS);
        free(delete);
        delete = NULL;
        remove_switch = 1;
      }
      /* when the node to be removed is at the end of the list */
      else if (current->parent == NULL && current != NULL) {
        delete = current;
        current = NULL;
        freeDiscs(delete->state, MAX_SLOTS);
        free(delete);
        delete = NULL;
        remove_switch = 1;
      }
      /* when the node to be removed is in the middle of the list */
      else {
        delete = current;
        current = current->parent;
        prev->parent = current;
        /* ---- line 266 and 267 below ---- */
        freeDiscs(delete->state, MAX_SLOTS);
        free(delete);
        delete = NULL;
        remove_switch = 1;
      }
    }
    if (remove_switch == 0) {
      prev = current;
      current = current->parent;
    }
    remove_switch = 0;
  }
  return head;
}

空闲列表功能:

/* free's an AST_Node list */
void freeList(struct AST_Node * list, int MAX_SLOTS) {
  struct AST_Node * current, * prev;
  current = list;
  /* when a list must be free'd, free it */
  if (current != NULL) {
    /* traverse and free until the last node */
    while (current != NULL) {
      prev = current;
      current = current->parent;
      /* ---- line 404 below ---- */
      freeDiscs(prev->state, MAX_SLOTS);
      free(prev);
      prev = NULL;
    }    
  }
}

免费光盘功能:

/* frees's a discs_slot list */
void freeDiscs(struct discs_slot * discs, int MAX_SLOTS) {
  int i = 0;
  struct discs_slot * temp;

  while (i < MAX_SLOTS) {
    temp = discs;
    discs = discs->next;
    /* ---- line 141 below ---- */
    free(temp);
    i++;
  }

}

相关代码主要来自:

  /* until reaching a solution or the maximum traversals allowed */
  while (!isGoal(best_current->state) && Towards_Solution < Solution_Count) {
    /* when the best current node has not already been expanded */
    if (!inClosed(closed_list, best_current, Max_Slots)) {
      /* expand it and add the nodes to the fringe */
      fringe_list = addFringe(fringe_list, best_current, goal_state, Max_Slots);
      /* add the expanded node to the closed list */
      closed_list = addClosed(closed_list, best_current);
    }
    /* when the best node is in the closed list */
    else {
      /* do nothing */
    }

    printSmallDiscs(best_current->state, Max_Slots);

    /* get a new best node to evaluate and remove it from the fringe */
    best_current = fringeTraverse(fringe_list, best_current, goal_state, Max_Slots);
    /* ---- line 104 below ---- */
    fringe_list = removeFringe(fringe_list, best_current, Max_Slots);

    Towards_Solution++;

    /* when all possible nodes have been expanded and no solution exists */
    if (fringe_list == NULL) {
      printf("No solution\n");
      break;
    }
  }



  /* return memory */
  freeDiscs(discs_list, Max_Slots);
  freeDiscs(goal_state, Max_Slots);

  freeList(best_current, Max_Slots);
  /* ---- line 129 below ---- */
  freeList(fringe_list, Max_Slots);
  freeList(closed_list, Max_Slots);

  return 0;

}

这是添加条纹功能:

/* creates new nodes from the best current state and adds those nodes to the fringe */
struct AST_Node * addFringe(struct AST_Node * list, struct AST_Node * best, struct discs_slot * goal, int MAX_SLOTS) {
  struct AST_Node * move_LCW, * move_LCCW, * move_ACW, * move_ACCW;
  struct AST_Node * current, * head, * prev;
  current = list;
  head = list;

  /* break apart the current best state for a possible solution */
    move_LCW = largeCW(best, goal, MAX_SLOTS);
    move_LCCW = largeCCW(best, goal, MAX_SLOTS);
    move_ACW = adjacentCW(best, goal, MAX_SLOTS);
    move_ACCW = adjacentCCW(best, goal, MAX_SLOTS);


  /* store these new nodes in the fringe */
  /* when storing in the fringe for the first time */
  if (current == NULL) {
    //printf("Empty Fringe:\n\n");
    current = move_LCW;
    current->parent = move_LCCW;
    current->parent->parent = move_ACW;
    current->parent->parent->parent = move_ACCW;
    current->parent->parent->parent->parent = NULL;
    //printf("List Start --------------------\n");
    //printList(current, MAX_SLOTS);
    //printf("List End --------------------\n");

  }
  /* when storing in a partially filled fringe */
  else {
    /* traverse to the end and start adding nodes from there */
    while (current != NULL) {
      prev = current;
      current = current->parent;
      //printf("*\n");
    }
    //printf("Fringe not empty new nodes added:\n\n");
    current = move_LCW;
    current->parent = move_LCCW;
    current->parent->parent = move_ACW;
    current->parent->parent->parent = move_ACCW;
    current->parent->parent->parent->parent = NULL;
    //printf("List Start --------------------\n");
    //printList(current, MAX_SLOTS);
    //printf("List End  --------------------\n");
    prev->parent = current;
    current = head;
  }

  //printf("Entire Fringe: \n\n");
  //printList(head, MAX_SLOTS);
  //printf("____________________\n");
  return current;
}

此函数复制大小为MAX_SLOTS的光盘列表(最终读取为NULL)

/* creates a copy of a disc slot list */
struct discs_slot * copy_dlist(struct discs_slot * discs, int MAX_SLOTS) {

  struct discs_slot * head, * current;

  current = malloc(sizeof(struct discs_slot));
  if (current == NULL) {
    printf("\nAn error ocurred when trying to allocate memory.\n");
    exit(0);
  }

  head = current;

  /* traverse for as many disc slots that exist and copy the data from
     the disc slot list passed in to the new one */
  for (int i = 0; i < MAX_SLOTS; i++) {
    current->large = discs->large;
    current->small = discs->small;
    current->position = discs->position;

    if (i < (MAX_SLOTS - 1)) {
      struct discs_slot * new_dslot;
      new_dslot = malloc(sizeof(struct discs_slot));
      if (new_dslot == NULL) {
    printf("\nAn error ocurred when trying to allocate memory.\n");
    exit(0);
      }

      current->next = new_dslot;
      current = new_dslot;
    }
    discs = discs->next;
  }

  current->next = head;
  current = head;

  return current;
}
曼托什·库玛

根据问题的症状,您的程序遇到某种无效的堆内存读取。通常,只要我们的程序在拥有free内存或free两次内存之后尝试读取,就会发生这种情况如果看到Valgrind报告摘要,则将获得以下信息:

total heap usage: 128 allocs, 134 frees, 3,112 bytes allocated

您的程序分配了128个分配,并尝试释放134个时间。这表示您的程序中出现双重免费的情况。由于在释放内存后为指针分配了NULL,因此稍后某个地方的程序遇到分段错误,而程序尝试访问NULL指针。

查看堆栈跟踪,几乎不可能找出造成此问题的根本原因,因为这些分段错误将是由于程序中的某些实际不良后果(释放内存后将指针设置为NULL)造成的。早期执行。

识别这些内存损坏最好的方法是使用GDBValgrind在一起。为此,您可能需要在Valgrind / GDB中附加程序(a.out)。

$ valgrind --tool=memcheck --db-attach=yes ./a.out

这样,当检测到第一个内存错误时,Valgrind会将程序附加到调试器中,以便您可以进行实时调试(GDB)。这应该是理解和解决问题的最佳方法。一旦能够找出第一个错误,就将其修复并重新运行,然后查看您还遇到了其他错误。应该执行此步骤,直到Valgrind报告没有错误为止。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

c Valgrind读取大小4无效->分段错误

来自分类Dev

读取的大小无效-C valgrind

来自分类Dev

C分段错误,大小为4的读取无效

来自分类Dev

我在C中运行Valgrind时收到大小为8的无效读取

来自分类Dev

大小8的无效读取,大小8(Valgrind)的无效写入

来自分类Dev

Valgrind 错误无效读取大小 4

来自分类Dev

使用boost :: smatch在valgrind中读取大小无效1

来自分类Dev

C ++无效的读取大小4 valgrind

来自分类Dev

使用valgrind时无效读取大小1

来自分类Dev

Valgrind:无效读取的8号错误

来自分类Dev

Valgrind:无效读取的8号错误

来自分类Dev

valgrind错误:无效的读取

来自分类Dev

valgrind对大小1的无效读取(realloc使错误“释放后使用条件”)

来自分类Dev

cpp-valgrind-大小为8的无效读取

来自分类Dev

cpp-valgrind-大小为8的无效读取

来自分类Dev

C从valgrind读取无效

来自分类Dev

使用valgrind无效读取俄罗斯方块中的大小1

来自分类Dev

Valgrind错误:使用由struct和malloc构成的列表时,大小为8的无效写入

来自分类Dev

valgrind中带有函数指针的读取大小无效

来自分类Dev

Valgrind大小为8的神秘无效写入错误

来自分类Dev

读取文件时valgrind中的错误-C

来自分类Dev

正确使用strcpy()并避免在valgrind中读取和写入大小错误

来自分类Dev

读取行时c中的分段错误

来自分类Dev

无效的读取-Valgrind和C

来自分类Dev

分段错误,大小为4的无效写入

来自分类Dev

Valgrind无效读取4号错误?

来自分类Dev

在C中创建动态数组读取器,分段错误

来自分类Dev

使用malloc的C中的分段错误

来自分类Dev

使用MinGW的C中的分段错误