c - Segmentation Fault in call to free() -


i have test case keeps throwing segmentation fault. when used gdb try , find segfaulting, found failed in call free() in code being tested.

now thing is, parameter being passed free() allocated using malloc() , wasn't adjusted after (afaict).

here's relevant code:

structure.h:

#pragma once  //===   includes  #include <stdint.h> #include <stdlib.h> #include <string.h> #include <stdio.h>  #include "kv/backend.h" #include "xm.h" #include "constants.h"  //===   defines  #define structure_type_null (0x00)  // invalid - should never see #define structure_type_sub  (0x01)  // substructure #define structure_type_i64  (0x02)  // 64b signed integer #define structure_type_u64  (0x03)  // 64b unsigned integer #define structure_type_h64  (0x04)  // 64b translate hex (ie: 0x'...') #define structure_type_f64  (0x05)  // 64b ieee 754 double float #define structure_type_blob (0x06)  // variable length binary blob #define structure_type_string   (0x07)  // variable length null terminated string #define structure_type_time (0x08)  // 64b packed ymdhms time #define structure_type_unixtime (0x09)  // 64b signed unix time  //===   structures  typedef struct {     int64_t     year    :35;     uint64_t    month   :4;     uint64_t    day :5;     uint64_t    hour    :5;     uint64_t    minute  :6;     uint64_t    second  :6; } structure_time;  typedef struct structure_struct {     uint8_t *key;     union {         int64_t         i64;         uint64_t        u64;         uint64_t        h64;         double          f64;         uint8_t         *blob;         uint8_t         *string;         structure_time      time;         int64_t         unixtime;         struct structure_struct *children;     };     union {         uint16_t    len;    // blob + string (includes null terminator)         uint16_t    count;  // children     };     uint8_t     type; } structure;  //===   special  static inline int cmp_structure (const void *arg1, const void *arg2) {     const structure *a = arg1;     const structure *b = arg2;     return strcmp (a->key, b->key); // compare keys }  #define sort_name structure #define sort_type structure #define sort_cmp(x, y)  cmp_structure (&x, &y) #include "../deps/sort/sort.h"  //===   functions  static inline void structuresortchildren (structure *s) {     structure_tim_sort (s->children, s->count);     return; }  int structureaddchildren    (structure *parent, const structure *children, int count); void structurefree      (structure *s); 

structure.c:

#include "structure.h"  int structureaddchildren (structure *parent, const structure *children, int count) {     if (parent->type != structure_type_sub)         return 1;   // yeah lets not cause memory issue      // realloc () may lose data     structure *tmp = malloc ((parent->count + count) * sizeof (structure *));     if (!tmp)         return -1;  // memory failure      // copy on old children     memcpy (tmp, parent->children, parent->count * sizeof (structure));     if (parent->count > 0)         free (parent->children);        // segfault occurs here     parent->children = tmp;      // copy on new children     memcpy (&parent->children[parent->count], children, count * sizeof (structure));     parent->count += count;      // resort array allow bsearch() find members     structure_tim_sort (parent->children, parent->count);      return 0; } 

test_structure.c:

#include "test.h" #include "../structure.h"  const char *key[4] = { "head", "number", "integer", "string" }; const char *text = "text";  void printstructure (const structure *s) {     switch (s->type) {         case structure_type_sub: {             printf ("structure:\n"  \                 "\ttype:\t%s\n" \                 "\tkey:\t%s\n"  \                 "\tnumber count:\t%i\n\n",                 "(sub)structure", s->key, s->count);             break;         }          case structure_type_string: { //          assert (s->len == (strlen (s->string) + 1));    // null terminator             printf ("structure:\n"  \                 "\ttype:\t%s\n" \                 "\tkey:\t%s\n"  \                 "\tvalue:\t%s\n" \                 "\tlength:\t%i\n\n",                 "string", s->key, s->string, s->len);             break;         }          case structure_type_i64: {             printf ("structure:\n"  \                 "\ttype:\t%s\n" \                 "\tkey:\t%s\n"  \                 "\tvalue:\t%i\n\n",                 "64-bit signed integer", s->key, (int) s->i64);             break;         }          case structure_type_f64: {             printf ("structure:\n"  \                 "\ttype:\t%s\n" \                 "\tkey:\t%s\n"  \                 "\tvalue:\t%f\n\n",                 "64-bit fp number", s->key, (float) s->f64);             break;         }     }      return; }  void test (void) {     structure *head, *number, *integer, *string;      // basic allocations     head = malloc (sizeof (structure));     head->key = strdup (key[0]);     head->type = structure_type_sub;     head->count = 0;      number = malloc (sizeof (structure));     number->key = strdup (key[1]);     number->type = structure_type_f64;     number->f64 = 3.1415;      integer = malloc (sizeof (structure));     integer->key = strdup (key[2]);     integer->type = structure_type_i64;     integer->i64 = -42;      string = malloc (sizeof (structure));     string->key = strdup (key[3]);     string->type = structure_type_string;     string->string = strdup (text);     string->len = strlen (text) + 1;    // null terminator      // lets see current states     printf ("\n---structures built---\n\n");     printstructure (head);     printstructure (number);     printstructure (integer);     printstructure (string);      // lets put them     // head +>  number     //  ->  integer     //  ->  string     structureaddchildren (head, integer, 1);     structureaddchildren (head, string, 1);     structureaddchildren (head, number, 1);     // segfault occurs on call      ... }  int main (int argc, char *argv) {     test ();     return 0; } 

now, segfault occurs on third invocation of structureaddchildren(). specifically, on line

structureaddchildren (head, number, 1); // segfault occurs on call

from test_structure.c, once structureaddchildren called, segfault occurs on line

free (parent->children); // segfault occurs here

from structure.c.

i can't imagine causing segfault, since structureaddchildren() point @ memory being allocated , nothing else messes pointer (writing it).


so, overall, causing segfault , how can resolve it?

when allocating memory new (and old) structures in structureaddchildren(), you've calculated new size using sizeof(structure *) when should sizeof(structure). result, insufficient space allocated , later writes overrun allocated space. corrected line should be:

structure *tmp = malloc ((parent->count + count) * sizeof (structure)); 

Comments