title: Calling qsort on Double Pointer Results in Segmentation Fault
body: <p>I've been working through a symbol table implementation for a while now and am quite confused on why this bit of code causes a segfault. </p>
  
  <pre><code>symbol_t** symbol_order (sym_table_t* symTab, int order) {
  symbol_t* sort = malloc(symTab-&gt;size * sizeof(symbol_t*)); //line 198
  int index = 0;
  for (int i = 0; i &lt;  symTab-&gt;capacity; i++) {
      node_t* nodePtr = symTab-&gt;hash_table[i];
      while(nodePtr != NULL) {
          sort[index] = nodePtr-&gt;symbol; //line 203
          nodePtr = nodePtr-&gt;next;
          index++;
      }
  }
  if (order == NAME) {
      qsort(sort, symTab-&gt;size, sizeof(symbol_t*),compare_names); //line 209
  } else if (order == ADDR) {
      qsort(sort, symTab-&gt;size, sizeof(symbol_t*),compare_addresses);
  }
  return sort;
  </code></pre>
  
  <p>The function is supposed to return a sorted array of type symbol_t** which includes every element from the hash table. I am using qsort with one of two compare methods:</p>
  
  <pre><code>int compare_names (const void* vp1, const void* vp2) {
      symbol_t* sym1 = *((symbol_t**) vp1);
      symbol_t* sym2 = *((symbol_t**) vp2);  // study qsort to understand this
      return strcmp(sym1-&gt;name, sym2-&gt;name); //line 185
  }
  
  int compare_addresses (const void* vp1, const void* vp2) {
      symbol_t* sym1 = *((symbol_t**) vp1);
      symbol_t* sym2 = *((symbol_t**) vp2);
      return sym1-&gt;addr - sym2-&gt;addr;
  }
  </code></pre>
  
  <p>My data structure is as follows:</p>
  
  <pre><code>struct sym_table {
    int      capacity;
    int      size;
    node_t** hash_table;
    char**   addr_table;
  };
  typedef struct sym_table sym_table_t;
  
  typedef struct node {
    struct node* next;
    int          hash;
    symbol_t     symbol;
  } node_t;
  
  typedef struct symbol {
      char* name; /**&lt; the name of the symbol */
      int   addr; /**&lt; symbol's address in the LC3 memory */
  } symbol_t;
  </code></pre>
  
  <p>I tried using Valgrind to find the source of the fault but I'm pretty new to it so I'm not sure what to make of it.</p>
  
  <ul>
  <li>I initialized a new symbol table with size 1 in order to keep it in
  one linked list. </li>
  <li>I added 3 elements to the table and then called the
  sort function to use the compare_names function.</li>
  </ul>
  
  <blockquote>
  <pre><code>==30693== Invalid write of size 8
  ==30693==    at 0x4012BA: symbol_order (symbol.c:203)
  ==30693==    by 0x401522: printList (testSymbol.c:123)
  ==30693==    by 0x401966: main (testSymbol.c:207)
  ==30693==  Address 0x5280cd8 is 0 bytes after a block of size 24 alloc'd
  ==30693==    at 0x4C2DB9D: malloc (vg_replace_malloc.c:299)
  ==30693==    by 0x401266: symbol_order (symbol.c:198)
  ==30693==    by 0x401522: printList (testSymbol.c:123)
  ==30693==    by 0x401966: main (testSymbol.c:207)
  ==30693==
  ==30693== Invalid write of size 8
  ==30693==    at 0x4012B7: symbol_order (symbol.c:203)
  ==30693==    by 0x401522: printList (testSymbol.c:123)
  ==30693==    by 0x401966: main (testSymbol.c:207)
  ==30693==  Address 0x5280ce0 is 8 bytes after a block of size 24 alloc'd
  ==30693==    at 0x4C2DB9D: malloc (vg_replace_malloc.c:299)
  ==30693==    by 0x401266: symbol_order (symbol.c:198)
  ==30693==    by 0x401522: printList (testSymbol.c:123)
  ==30693==    by 0x401966: main (testSymbol.c:207)
  ==30693==
  ==30693== Invalid read of size 8
  ==30693==    at 0x4011FD: compare_names (symbol.c:185)
  ==30693==    by 0x4E7362D: msort_with_tmp.part.0 (msort.c:83)
  ==30693==    by 0x4E732F6: msort_with_tmp (msort.c:45)
  ==30693==    by 0x4E732F6: msort_with_tmp.part.0 (msort.c:54)
  ==30693==    by 0x4E73A7E: msort_with_tmp (msort.c:45)
  ==30693==    by 0x4E73A7E: qsort_r (msort.c:297)
  ==30693==    by 0x401308: symbol_order (symbol.c:209)
  ==30693==    by 0x401522: printList (testSymbol.c:123)
  ==30693==    by 0x401966: main (testSymbol.c:207)
  ==30693==  Address 0x3 is not stack'd, malloc'd or (recently) free'd
  ==30693==
  ==30693==
  ==30693== Process terminating with default action of signal 11 (SIGSEGV): dumping core
  ==30693==  Access not within mapped region at address 0x3
  ==30693==    at 0x4011FD: compare_names (symbol.c:185)
  ==30693==    by 0x4E7362D: msort_with_tmp.part.0 (msort.c:83)
  ==30693==    by 0x4E732F6: msort_with_tmp (msort.c:45)
  ==30693==    by 0x4E732F6: msort_with_tmp.part.0 (msort.c:54)
  ==30693==    by 0x4E73A7E: msort_with_tmp (msort.c:45)
  ==30693==    by 0x4E73A7E: qsort_r (msort.c:297)
  ==30693==    by 0x401308: symbol_order (symbol.c:209)
  ==30693==    by 0x401522: printList (testSymbol.c:123)
  ==30693==    by 0x401966: main (testSymbol.c:207)
  ==30693==  If you believe this happened as a result of a stack
  ==30693==  overflow in your program's main thread (unlikely but
  ==30693==  possible), you can try to increase the size of the
  ==30693==  main thread stack using the --main-stacksize= flag.
  ==30693==  The main thread stack size used in this run was 8388608.
  ==30693==
  ==30693== HEAP SUMMARY:
  ==30693==     in use at exit: 524,480 bytes in 13 blocks
  ==30693==   total heap usage: 15 allocs, 2 frees, 526,528 bytes allocated
  ==30693==
  ==30693== LEAK SUMMARY:
  ==30693==    definitely lost: 0 bytes in 0 blocks
  ==30693==    indirectly lost: 0 bytes in 0 blocks
  ==30693==      possibly lost: 0 bytes in 0 blocks
  ==30693==    still reachable: 524,480 bytes in 13 blocks
  ==30693==         suppressed: 0 bytes in 0 blocks
  ==30693== Rerun with --leak-check=full to see details of leaked memory
  ==30693==
  ==30693== For counts of detected and suppressed errors, rerun with: -v
  ==30693== ERROR SUMMARY: 4 errors from 3 contexts (suppressed: 0 from 0)
  </code></pre>
  </blockquote>
  
  <p>I'm pretty sure it has something to do with an allocation error where I allocated the single array to put all of the elements on line 203 and maybe the return type issue. I've marked all the lines that are referenced in the error report. </p>
  
  <p>Is there something I'm missing? I've tried changing many things around as per other similar posts on Stack Overflow with either no change or even more problems.</p>