简体   繁体   中英

Valgrind "Invalid write of size n" when using malloc

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 *));

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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM