views:

84

answers:

2

I have a C assignment. It is a lot longer than the code shown below, and we are given the function prototypes and instructions only. I have done my best at writing code, but I am stuck with segmentation faults. When I compile and run the program below on Linux, at "735 NaN" it will terminate, indicating a segfault occurred. Why? What am I doing wrong? Basically, the program does not let me access table->list_array[735]->value and table->list_array[735]->key. This is of course the first segfault. There might be more following index 735.

#include <stdio.h>
#include <stdlib.h>

typedef struct list_node list_node_t;

struct list_node
{ 
  char *key;
  int value;
  list_node_t *next;
};

typedef struct count_table count_table_t;

struct count_table {
  int size;
  list_node_t **list_array;
};


count_table_t* table_allocate(int size) 
{
    count_table_t *ptr = malloc(sizeof(count_table_t));

    ptr->size = size;

    list_node_t *nodes[size];

    int k;

    for(k=0; k<size; k++){
       nodes[k] = NULL;
    }

    ptr->list_array = nodes;

    return ptr;
}

void table_addvalue(count_table_t *table) 
{
    int i;

    for(i=0; i<table->size; i++)
    {
       table->list_array[i] = malloc(sizeof(list_node_t));
       table->list_array[i]->value = i;
       table->list_array[i]->key = "NaN";
       table->list_array[i]->next = NULL;
    }
}

int main()
{
      count_table_t *table = table_allocate(1000);
      table_addvalue(table);

      int i;

      for(i=0; i<table->size; i++)
          printf("%d  %s\n", table->list_array[i]->value, table->list_array[i]->key); 

      return 0;
}
+2  A: 

You're point ptr->list_array at a local variable (nodes) in table_allocate, which goes away when that function returns, leaving a dangling pointer. You probably want

list_node_t **nodes = malloc(size * sizeof(list_node_t *));
Chris Dodd
Thanks a lot. You helped me fix the problem.
What is the difference between (size * sizeof(list_node_t *)) and (size * sizeof(list_node_t)) ?? The latter does not have an asterisk, and I have also noticed the latter allocates a lot more memory.
`list_node_t *` refers to a pointer -- the size of a pointer to any type depends only on your machine/compiler, typically 32 bits or 64 bits (it's essentially just an integer). `sizeof(list_node_t)` is enough to hold the size of a `list_node_t` instance, that is enough for all the members of `list_node_t` plus some padding if applicable. Here that's `sizeof(char *) + sizeof(int) + sizeof(list_node_t *)`
isbadawi
+1  A: 

I recommend the routine use of valgrind(1) to prevent such problems from occurring.

Steve Emmerson