分段错误但无法推理,内存分配对我来说看起来不错 [英] Segmentation fault but unable to reason how, memory allocation looks fine to me

查看:17
本文介绍了分段错误但无法推理,内存分配对我来说看起来不错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个节点,我定义它的全局指针变量如下:

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 used calloc 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆