分段错误但无法解释如何,内存分配对我来说很好看

我有一个节点,我正在定义其全局指针变量,如下所示:

typedef struct node { char* word; struct node* next; } node; node* HashTable = NULL; node* HeadOfHashTable = NULL; 

现在,我分配了如下内存:

 void allocateMemory(int numOfElements, bool isRealloc, const char* word) { if(!isRealloc) { printf("Allocating %d blocks\n", numOfElements); HashTable = malloc(sizeof(node*) * numOfElements); } else { printf("Reallocating %d blocks for %s", numOfElements, word); HashTable = realloc(HashTable, sizeof(node*) * numOfElements); } if(HashTable == NULL) { printf("### Out Of Memory ###\n"); exit(0); } HeadOfHashTable = HashTable; } 

现在,我传递一个HASH值和单词放入哈希表,在下面的方法中。 我已经评论了我在哪里遇到了seg错误。

 void putInHashTable(char* ch, unsigned int hashValue) { HashTable += hashValue; printf("Processing at address: %p and has value was %d\n", HashTable, hashValue); if(HashTable == NULL || HashTable == '\0' || HashTable == 0) { printf("Hash table is NULL"); } if(HashTable->word == NULL) { HashTable->word = malloc(sizeof(char) * (LENGTH + 1)); strcpy(HashTable->word, ch); printf("New word: %s\n", HashTable->word); } else { printf("### Collision detected ###\n"); // ***** BELOW LINE GIVES SEG FAULT ****** printf(" Earlier value is %s, new value is %s and its pointer is %p\n", HashTable->word, ch, HashTable->next); putInLinkedList(ch); } HashTable = HeadOfHashTable; } 

以下是控制台日志:

 Allocating 65336 blocks Processing at address: 0xb7568c28 and has value was 388 New word: a Processing at address: 0xb756b9a0 and has value was 1843 New word: aaa Processing at address: 0xb7570c08 and has value was 4480 New word: aaas Processing at address: 0xb75ae608 and has value was 36032 ### Collision detected ### Segmentation fault (core dumped) 

我的疑惑:

  • 我正在分配65336块内存,而我得到段错误的点的哈希值为36032,所以我确信指针变量HashTable具有有效的内存地址。 然后为什么seg故障?
  • 如果它不是一个有效的地址,那么为什么它没有陷入这个IF条件if(HashTable == NULL || HashTable == '\0' || HashTable == 0) 。 我甚至使用calloc然后我得到seg故障和上面的IF条件没有捕获。
  • 我在此行printf(" Earlier value is %s, new value is %s and its pointer is %p\n", HashTable->word, ch, HashTable->next);得到seg错误printf(" Earlier value is %s, new value is %s and its pointer is %p\n", HashTable->word, ch, HashTable->next); 。 这意味着在解除指针时出现一些问题,那么为什么我之前没有得到段错误,这意味着我应该只在这里遇到段错误 – if(HashTable->word == NULL)

数着星星。

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

经验法则:在任务的任何一方,星星的数量必须相同。 为什么?

  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 

好代码的其他例子:

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

不好的代码:

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

你的路线

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

(在替换为node*HashTable类型之后)直接落入坏代码箱中,因此尝试解决这个问题。

如果你想要一个节点数组:

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

如果你想要一组pouners到节点,你也可以拥有它。 这并不是真的值得推荐,因为节省的空间很小,性能下降可能会很大,并且代码不那么优雅。 但你可以拥有它:

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

恭喜! 你现在有一个numOfElements数组未初始化的指针。 现在您需要将它们初始化为某个值,通常为NULL:

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

每次要将值放入表时,您需要分配一个新node

 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 } 

在我们处理它时,请注意这些与主要问题相关的时刻:如何正确检查NULL,如何检查malloc的返回值,以及如何使用数组索引而不是改变全局指针变量来回。 (如果要使用指针运算,请在putInHashTable使用本地指针变量)。

(当然,如果你不使用n_foos,或者使用calloc,你需要对星数进行心理调整)。