带有指针和结构的链表

时间:2017-04-09 09:04:27

标签: c pointers struct valgrind

我试图用c中的指针和结构编写一个链表。在控制台上我的小例子正在运行但是只要我想检查 valgrind 返回什么,就会出现下面的输出。

我认为它类似于越界异常,但我不知道如何解释并以正确的方式解决它。

源代码:

int main(){
  struct node {
      int data;
      struct node *nextNode;
  };

  int counter = 10;
  struct node *nodeSpace;

  nodeSpace = (struct node *) malloc(counter * sizeof(struct node));
  struct node *base = nodeSpace;

  for(int i = 0; i < counter; i++){
      int offset = i * sizeof(struct node);
      struct node *currentNode;

      currentNode = base + offset;
      currentNode->data = i;

      if(i == counter-1)
          currentNode->nextNode = NULL;
      else
          currentNode->nextNode = base + (i+1)*sizeof(struct node);

      printf("Node (%i): Address: %p Data: %i Next: %p\n", 
             i, currentNode, currentNode->data, currentNode->nextNode);
   }
   return 0;
}

Valgrind的:

Node (0): Address: 0x5203040 Data: 0 Next: 0x5203140
Node (1): Address: 0x5203140 Data: 1 Next: 0x5203240
Node (2): Address: 0x5203240 Data: 2 Next: 0x5203340
Node (3): Address: 0x5203340 Data: 3 Next: 0x5203440
Node (4): Address: 0x5203440 Data: 4 Next: 0x5203540
==23418== Invalid write of size 4
==23418==    at 0x4005DC: main (linkedList.c:18)
==23418==  Address 0x5203540 is 32 bytes before an unallocated block of size 4,192,896 in arena "client"
==23418== 

来自valgrind的错误显示在行

currentNode->data = i;

如果有人可以帮助我,那真的很好,谢谢。

1 个答案:

答案 0 :(得分:1)

类型指针算法保留底层元素的步幅,作为地址计算的一部分。给定非p类型指针p[i] ,这就是

的原因
*(p+i)

int ar[2];
int *p = ar;
int *q = p+1;

printf("p = %p\n", (const void*)p);
printf("q = %p\n", (const void*)q);

是同义词。

要查看元素宽度的自动使用,请考虑:

p = 0x7fff5fbff9d0
q = 0x7fff5fbff9d4

样本输出(变化)

int

注意#include <stdio.h> #include <stdlib.h> int main() { struct node { int data; struct node *nextNode; }; int counter = 10; struct node *nodeSpace = malloc(counter * sizeof(struct node)); for(int i = 0; i < counter; i++) { struct node *currentNode = nodeSpace + i; currentNode->data = i; if(i == counter-1) currentNode->nextNode = NULL; else currentNode->nextNode = currentNode+1; printf("Node (%i): Address: %p Data: %i Next: %p\n", i, currentNode, currentNode->data, currentNode->nextNode); } free(nodeSpace); return 0; } 的大小已被考虑(在这种情况下,它是四个字节)。

那就是说,你的代码简化为:

Node (0): Address: 0x1001053a0 Data: 0 Next: 0x1001053b0
Node (1): Address: 0x1001053b0 Data: 1 Next: 0x1001053c0
Node (2): Address: 0x1001053c0 Data: 2 Next: 0x1001053d0
Node (3): Address: 0x1001053d0 Data: 3 Next: 0x1001053e0
Node (4): Address: 0x1001053e0 Data: 4 Next: 0x1001053f0
Node (5): Address: 0x1001053f0 Data: 5 Next: 0x100105400
Node (6): Address: 0x100105400 Data: 6 Next: 0x100105410
Node (7): Address: 0x100105410 Data: 7 Next: 0x100105420
Node (8): Address: 0x100105420 Data: 8 Next: 0x100105430
Node (9): Address: 0x100105430 Data: 9 Next: 0x0

输出(示例)

var myElement = document.getElementsByClassName("demo");