valgrind'尺寸的写作无效n&quot使用malloc时

发布于 2025-02-01 12:44:05 字数 1418 浏览 4 评论 0原文

我正在使用此结构创建图形

struct node
{
  int id;
  struct node *ad;
};

struct graph
{
  int numVert;
  struct node **adjList;
  int *visited;
  int *back;
};

,并使用它来分配内存,

static struct graph *graph_create(struct world *W, int v)
{
  struct graph *G = NULL;

  if ((G = graph_alloc(v)) != NULL)
  {
    /* some stuff */
  }

  return G;
}

static struct graph *graph_alloc(int v)
{
  struct graph *G = NULL;
  int i;
  struct node **newNode = NULL;

  if ((G = (struct graph *)malloc(sizeof(struct graph *))) != NULL)
  {
    G->numVert = v;
    G->adjList = (struct node **)malloc(v * sizeof(struct node *));
  }

  /* other stuff */

  return G;
}

但是当我使用-s-leak-check = full-show-show-show-leak-kinds = all进行编译时,Valgrind向我展示了这一点。而且我不知道为什么

==65390== Invalid write of size 8
==65390==    at 0x10985D: graph_alloc (main.c:299)
==65390==    by 0x109801: graph_create (main.c:283)
==65390==    by 0x10925F: main (main.c:75)
==65390==  Address 0x4a429c8 is 0 bytes after a block of size 8 alloc'd
==65390==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==65390==    by 0x109830: graph_alloc (main.c:296)
==65390==    by 0x109801: graph_create (main.c:283)
==65390==    by 0x10925F: main (main.c:75)

我认为问题是那排没有它,没有错误

G->adjList = (struct node **)malloc(v * sizeof(struct node *));

I'm creating a graph using this structures

struct node
{
  int id;
  struct node *ad;
};

struct graph
{
  int numVert;
  struct node **adjList;
  int *visited;
  int *back;
};

And using this to allocate the memory

static struct graph *graph_create(struct world *W, int v)
{
  struct graph *G = NULL;

  if ((G = graph_alloc(v)) != NULL)
  {
    /* some stuff */
  }

  return G;
}

static struct graph *graph_alloc(int v)
{
  struct graph *G = NULL;
  int i;
  struct node **newNode = NULL;

  if ((G = (struct graph *)malloc(sizeof(struct graph *))) != NULL)
  {
    G->numVert = v;
    G->adjList = (struct node **)malloc(v * sizeof(struct node *));
  }

  /* other stuff */

  return G;
}

But valgrind show me this when i compile using -s --leak-check=full --show-leak-kinds=all and i don't know why

==65390== Invalid write of size 8
==65390==    at 0x10985D: graph_alloc (main.c:299)
==65390==    by 0x109801: graph_create (main.c:283)
==65390==    by 0x10925F: main (main.c:75)
==65390==  Address 0x4a429c8 is 0 bytes after a block of size 8 alloc'd
==65390==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==65390==    by 0x109830: graph_alloc (main.c:296)
==65390==    by 0x109801: graph_create (main.c:283)
==65390==    by 0x10925F: main (main.c:75)

I think the problem is that row becouse without it there is no error

G->adjList = (struct node **)malloc(v * sizeof(struct node *));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乄_柒ぐ汐 2025-02-08 12:44:05

当您尝试在此处为图形结构分配内存时:

struct graph *G = NULL;

G = (struct graph *) malloc(sizeof(struct graph *));

您仅为指向结构的指针分配内存,但是您需要为指针指向的内容分配内存:

struct graph *G = malloc(sizeof(*G));

您还可以指定类型的大小:

struct graph *G = malloc(sizeof(struct graph));

但是我喜欢成语类型 *p = malloc(sizeof( *p))。您从malloc获得的指针是您分配给定尺寸的内存的处理。重要的不是指针的大小重要,而是指向指向的大小,即*p

在您的情况下,图形结构由三个指针和一个整数组成,因此图形结构比指向图形结构的指针所需的内存更多。这就是导致无效写作的原因。

两个观察结果:

  • 在C中,铸件对(struct Graph *)是不需要的,因为void *可以转换为指针转换为其他东西。

  • 我发现在子句中同时进行分配和null检查,从而使代码很难看到正在发生的事情。而不是

      struct Graph *g = null;
    
    if((g = malloc(sizeof(*g)))!= null)...
     

    我更喜欢:

      struct Graph *g = malloc(sizeof( *g));
    
    如果(g!= null)...
     

    将内存分配与成功测试分开。它的括号也更少。 :)(这也许是个人品味的问题,但我的印象是初学者非常喜欢这些复杂的结构。保持简单。)

When you try to allocate memory for your graph structure here:

struct graph *G = NULL;

G = (struct graph *) malloc(sizeof(struct graph *));

you allocate memory only for a pointer to the structure, but you need to allocate memory for the thing the pointer points at:

struct graph *G = malloc(sizeof(*G));

You could also specify the size of the type:

struct graph *G = malloc(sizeof(struct graph));

but I like the idiom Type *p = malloc(sizeof(*p)). The pointer you get from malloc is a handle to the memory of the given size you have allocated. It's not the size of the pointer p that matters, but the size of what it points to, namely *p.

In your case the graph struct is made up of three pointers and an integers, so the graph struct requires more memory than a pointer to the graph struct. That is what causes the invalid writes.

Two observations:

  • In C, the cast to (struct graph *) is not necessary, because void * can be converted to a pointer to something else.

  • I find doing both the assignment and the null check in the if clause clutters the code and makes it hard to see what's going on. Instead of

    struct graph *G = NULL;
    
    if ((G = malloc(sizeof(*G))) != NULL) ...
    

    I'd prefer:

    struct graph *G = malloc(sizeof(*G));
    
    if (G != NULL) ...
    

    which separates the memory allocation from the test for success. It also has way fewer parentheses. :) (That's a matter of personal taste perhaps, but my impression is that beginners are very fond of these complicated constructions. Keep it simple.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文