Segmentation fault but unable to reason how, memory allocation looks fine to me

后端 未结 1 2043
旧巷少年郎
旧巷少年郎 2020-12-22 09:10

I have a node and I am defining its global pointer variable as below:

typedef struct node
{
    char* word;
    struct node* next;
} node;

node* HashTable =         


        
相关标签:
1条回答
  • 2020-12-22 09:24

    Counting the stars.

     FOO * foo_ptr = malloc (sizeof (FOO) * n_foos);
     //  ^                                ^             
     //  |                                |
     //  one star to the left of `=`      one star to the right of `=`
    

    The rule of thumb: the number of stars must be the same at either side of the assignment. Why?

          sizeof(FOO)    sizeof(FOO)    sizeof(FOO)   
         _____________  _____________  ______________
        /             \/             \/              \
         _____________  _____________  ______________
        [_____FOO_____][_____FOO_____][______FOO_____]
        ^
        |
        FOO* foo_ptr; // a FOO* points to a FOO
                      // pointer arithmetic works by incrementing the address\
                      // by sizeof(FOO)
                      // and so on
    

    Other examples of good code:

     FOO ** foo_ptr = malloc (sizeof (FOO*) * n_foos); // same number of stars
     FOO *** foo_ptr = malloc (sizeof (FOO**) * n_foos); // still same
    

    Bad code:

     FOO ** foo_ptr = malloc (sizeof (FOO) * n_foos); // numbers don't match
     FOO * foo_ptr = malloc (sizeof (FOO*) * n_foos); // numbers don't match
    

    Your line

    HashTable = malloc(sizeof(node*) * numOfElements);
    

    (after substituting the type of HashTable which is node*) falls squarely into the bad code bin, so try to fix that.

    If you want an array of nodes:

    HashTable = malloc(sizeof(node) * numOfElements);
    

    If you want an array of pouners to nodes, you can have that too. This is not really recommended, because space savings are small, performance degradation will probably be substantial, and the code is less elegant. But you can have it:

    node** HashTable = malloc(sizeof(node*) * numOfElements); // count! the! stars!
    

    Congratulations! You now have an array of numOfElements uninitialized pointers. Now you need to initialize them to some value, typically NULL:

    for (i = 0; i < numOfElements; ++i) HashTable[i] = NULL;
    

    And you need to allocate a new node each time you want to put a value to the table:

    if (HashTable[hashValue] == NULL) 
    {
      HashTable[hashValue] = malloc(sizeof(node));
      if (HashTable[hashValue] == NULL) 
      {
        panic ("Out of memory!");
      }
      HashTable[hashValue]->word = ...
      HashTable[hashValue]->next = ...
    } 
    else 
    {
      // collision etc
    }
    

    While we're at it, please note these moments which are tangential to the main question: how to properly check for NULL, how to check the return value of malloc, and how to use an array index instead of mutating a global pointer variable back and forth. (If you want to use pointer arithmetic, have a local pointer variable in putInHashTable).

    (Of course if you don't use n_foos, or use calloc, you need to make mental adjustments to the number of stars).

    0 讨论(0)
提交回复
热议问题