分段错误但无法推理,内存分配对我来说看起来不错 [英] Segmentation fault but unable to reason how, memory allocation looks fine to me
问题描述
我有一个节点,我定义它的全局指针变量如下:
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 = NULL;
node* HeadOfHashTable = NULL;
现在,我分配的内存如下:
Now, I allocated memory as below:
void allocateMemory(int numOfElements, bool isRealloc, const char* word)
{
if(!isRealloc)
{
printf("Allocating %d blocks
", 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 ###
");
exit(0);
}
HeadOfHashTable = HashTable;
}
现在,我在下面的方法中传递一个 HASH 值和单词以放入哈希表中.我已经评论了我遇到段错误的地方.
Now, I am passing a HASH value and word to put in hash table, in below method. I have commented where I am getting seg fault.
void putInHashTable(char* ch, unsigned int hashValue)
{
HashTable += hashValue;
printf("Processing at address: %p and has value was %d
", 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: %s
", HashTable->word);
} else {
printf("### Collision detected ###
"); // ***** BELOW LINE GIVES SEG FAULT ******
printf(" Earlier value is %s, new value is %s and its pointer is %p
", 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
具有有效的内存地址.那为什么会出现段错误? - 如果它不是一个有效地址,那么为什么它没有在这个 IF 条件中被捕获
if(HashTable == NULL || HashTable == ' ' || HashTable == 0)
.我什至使用了calloc
然后我也得到了 seg 错误并且上面的 IF 条件没有被捕获. - 我在这一行遇到 seg 错误
printf("早先的值是 %s,新的值是 %s,它的指针是 %p ", HashTable->word, ch, HashTable->下一个);代码>.这意味着在取消引用指针时会出现一些问题,那么为什么在此之前我没有遇到段错误,这意味着我应该只在这里遇到段错误 -
if(HashTable->word == NULL)代码>?
- I am allocating 65336 blocks of memory and the point where I am getting seg fault has hash value of 36032, so I am sure that pointer variable
HashTable
is having a valid memory address. Then why seg fault? - If it is not a valid address then why it is not caught in this IF condition
if(HashTable == NULL || HashTable == ' ' || HashTable == 0)
. I even usedcalloc
then also I get seg fault and above IF condition is not catching. - I am getting seg fault at this line
printf(" Earlier value is %s, new value is %s and its pointer is %p ", HashTable->word, ch, HashTable->next);
. This means some issue while de-referncing the pointer, then why I didn't get seg fault just before that, means I should have got seg fault here only -if(HashTable->word == NULL)
?
推荐答案
数星星.
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
其他优秀代码示例:
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);
(将 HashTable
的类型替换为 node*
后)直接落入了错误代码箱,因此请尝试修复它.
(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!
恭喜!你现在有一个 numOfElements
uninitialized 指针数组.现在您需要将它们初始化为某个值,通常为 NULL:
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;
而且每次你想给表放一个值时,你都需要分配一个新的node
:
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
}
在我们讨论的时候,请注意这些与主要问题相切的时刻:如何正确检查 NULL,如何检查 malloc
的返回值,以及如何使用数组索引而不是来回改变全局指针变量.(如果你想使用指针算法,在 putInHashTable
中有一个 local 指针变量.
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
).
(当然如果你不使用n_foos,或者使用calloc,你需要对star数进行心理调整).
(Of course if you don't use n_foos, or use calloc, you need to make mental adjustments to the number of stars).
这篇关于分段错误但无法推理,内存分配对我来说看起来不错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!