分段错误,但无法理性内存分配如何,看起来好像没什么问题 [英] Segmentation fault but unable to reason how, memory allocation looks fine to me

查看:85
本文介绍了分段错误,但无法理性内存分配如何,看起来好像没什么问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个节点,我如下定义其全球指针变量:

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\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值和字摆在哈希表,在下面的方法。我有评论那里我得到赛格故障。

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\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;
}

下面是控制台日志:

Below is console logs:

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条件抓到如果(哈希表== NULL ||哈希表=='\\ 0'||哈希表== 0)。我甚至用 释放calloc ,然后我也得到赛格故障及以上IF条件不捕。

  • 我收到赛格故障在该行的printf(此前值为%S,新值%s和它的指针%P \\ N,HashTable->文字,CH,哈希表 - >接着); 。这意味着一些问题,而脱referncing指针,那么为什么我以前不只是拿到赛格故障,意味着我应该得到赛格故障这里只 - 如果(HashTable->字== 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 == '\0' || 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\n", 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

不错code的其他例子:

Other examples of good code:

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

坏code:

 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 的类型之后节点* )正视落入坏code斌,所以尽量解决这个问题。

(after substituting the type of HashTable which is node*) falls squarely into the bad code bin, so try to fix that.

如果你想节点的数组:

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

如果你想pouners数组为节点,可以有这一点。这是不是真的建议,因为节省了空间小,性能下降可能是巨大的,而code是那么优雅。但是,你可以把它:

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 初始化指针数组。现在,你需要将它们初始化为一些值,通常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;

而你需要你想要把一个值表的新<​​code>节点每次分配:

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指针变量)。

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,你需要做心理调整数星星)。

(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天全站免登陆