我有一个节点,我正在定义它的全局指针变量,如下所示:
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 blocksn", 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 值和单词以放入哈希表中,在下面的方法中。我已经评论了我在哪里得到赛格错误。
void putInHashTable(char* ch, unsigned int hashValue)
{
HashTable += hashValue;
printf("Processing at address: %p and has value was %dn", HashTable, hashValue);
if(HashTable == NULL || HashTable == ' ' || 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: %sn", 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 %pn", 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 个内存块,而我遇到 seg 错误的点的哈希值为 36032,因此我确定指针变量
HashTable
具有有效的内存地址。那为什么是赛格的错呢? - 如果它不是有效的地址,那么为什么它没有被捕获在此 IF 条件中
if(HashTable == NULL || HashTable == ' ' || HashTable == 0)
.我什至使用了calloc
然后我也得到了 seg 错误,并且高于 IF 条件没有捕获。 - 我在这条线上遇到了赛格错误
printf(" Earlier value is %s, new value is %s and its pointer is %pn", HashTable->word, ch, HashTable->next);
.这意味着在取消引用指针时会出现一些问题,那么为什么我在那之前没有遇到 seg 错误,这意味着我应该只在这里遇到 seg 错误 -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);
如果你想要一个节点的pouner数组,你也可以拥有它。实际上不建议这样做,因为节省的空间很小,性能下降可能会很大,并且代码不太优雅。但你可以拥有它:
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,则需要对星星的数量进行心理调整)。