hag*_*wal 0 c pointers segmentation-fault
我有一个节点,我正在定义其全局指针变量,如下所示:
typedef struct node
{
char* word;
struct node* next;
} node;
node* HashTable = NULL;
node* HeadOfHashTable = NULL;
Run Code Online (Sandbox Code Playgroud)
现在,我分配了如下内存:
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;
}
Run Code Online (Sandbox Code Playgroud)
现在,我正在传递一个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;
}
Run Code Online (Sandbox Code Playgroud)
以下是控制台日志:
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)
Run Code Online (Sandbox Code Playgroud)
我的疑惑:
HashTable具有有效的内存地址.然后为什么seg故障?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故障,这意味着我应该只在这里遇到段故障 - if(HashTable->word == NULL)?数着星星.
FOO * foo_ptr = malloc (sizeof (FOO) * n_foos);
// ^ ^
// | |
// one star to the left of `=` one star to the right of `=`
Run Code Online (Sandbox Code Playgroud)
经验法则:在任务的任何一方,星星的数量必须相同.为什么?
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
Run Code Online (Sandbox Code Playgroud)
好代码的其他例子:
FOO ** foo_ptr = malloc (sizeof (FOO*) * n_foos); // same number of stars
FOO *** foo_ptr = malloc (sizeof (FOO**) * n_foos); // still same
Run Code Online (Sandbox Code Playgroud)
不好的代码:
FOO ** foo_ptr = malloc (sizeof (FOO) * n_foos); // numbers don't match
FOO * foo_ptr = malloc (sizeof (FOO*) * n_foos); // numbers don't match
Run Code Online (Sandbox Code Playgroud)
你的路线
HashTable = malloc(sizeof(node*) * numOfElements);
Run Code Online (Sandbox Code Playgroud)
(取代型之后HashTable是node*)完全属于成坏码仓,所以要尽量解决这个问题.
如果你想要一个节点数组:
HashTable = malloc(sizeof(node) * numOfElements);
Run Code Online (Sandbox Code Playgroud)
如果你想要一组pouners到节点,你也可以拥有它.这不是真正推荐的,因为节省的空间很小,性能下降可能很大,并且代码不那么优雅.但你可以拥有它:
node** HashTable = malloc(sizeof(node*) * numOfElements); // count! the! stars!
Run Code Online (Sandbox Code Playgroud)
恭喜!你现在有一个numOfElements 未初始化的指针数组.现在您需要将它们初始化为某个值,通常为NULL:
for (i = 0; i < numOfElements; ++i) HashTable[i] = NULL;
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
虽然我们正在讨论它,但请注意这些与主要问题相关的时刻:如何正确检查NULL,如何检查返回值malloc,以及如何使用数组索引而不是改变全局指针变量和向前.(如果要使用指针运算,请在本地指针变量中使用putInHashTable).
(当然,如果你不使用n_foos,或者使用calloc,你需要对星数进行心理调整).