【问题标题】:Error when using malloc for a struct将 malloc 用于结构时出错
【发布时间】:2015-11-13 03:21:22
【问题描述】:

我正在为家庭作业创建哈希表。我正在使用 Xcode,它没有任何即时错误,但是当我尝试运行它时,当涉及到最初创建哈希表并为其分配的函数时,我得到了 Thread 1:EXC_BAD_ACCESS 错误之一。特别是使用 malloc 的行:

Node **ht_create(void)
{

   Node **hashtable[htsize];

   int Node_size = sizeof(Node);

   if( htsize < 1 )
   {
       printf("Error: please enter adequate size for hashtable");
       return NULL;
   }

   for (int i = 0; i<=htsize;i++)
   {
   hashtable[i] = malloc(Node_size);
   }

   if( ( **hashtable)  == NULL )
   {
       printf("Error: could not allocate memory for hashtable");
       return NULL;
   }


    return *hashtable;
}

我对 C 语言还很陌生,我才 2 个月前才开始学习它,所以如果有明显的问题并且我只是个白痴,请多多包涵。 htsize 是在别处声明的整数命令行参数。我不知道它是否有帮助,但这里是定义我的“节点”结构的代码:

struct NodeType
{
    char *key;
    int value;
    struct NodeType *next;
};


typedef struct NodeType Node;

在黑暗中射击:这是否与我在结构中有指针这一事实有关? struct NodeType *next; 部分?

任何帮助将不胜感激,在此先感谢。

编辑:我现在有了它,所以它使用 for 循环为表中的每个节点分配,但它返回我的“错误:无法为哈希表分配内存”所以我的哈希表现在 = NULL?

【问题讨论】:

  • 顺便说一句,有些人认为 typedef 结构是不好的做法。由于您是 C 的新手,因此您应该研究一下。
  • @Bobby Sacamano 顺便说一句,有些人,包括 C11 规范,不认为 typedef 结构是不好的做法。你应该调查一下。
  • @chux 是的,这就是我建议调查这个问题的原因。我知道很多教授(至少在我的大学)表现得好像这只是标准的做法。
  • 也许您打算以通常的方式分配一个二维数组?
  • @BobbySacamano 使用 typedef 是作业的一部分,但感谢您的提示

标签: c pointers struct malloc


【解决方案1】:

不完全清楚 OP 的意图,但我希望 Node **ht_create(void) 创建并返回指向 Node * 数组的指针,因此返回类型 Node **。然后数组元素将被初始化为NULL,因为每个哈希表桶的开头都是一个空列表。

提示:分配内存的简单方法。

Some_type *pointer = malloc(sizeof *pointer * array_size);

示例代码:

Node **ht_create(size_t htsize) { // pass in size
  if (htsize < 1) {
    printf("Error: please enter adequate size for hashtable");
    return NULL;
  }

  //allocate hashtable
  Node **hashtable = malloc(sizeof *hashtable * htsize);
  if (hashtable == NULL) {
    printf("Error: could not allocate memory for hashtable");
    return NULL;
  }

  // Initialize values
  for (size_t i=0; i<htsize; i++) {
    hashtable[i] = NULL;
   }
  return hashtable;
}

【讨论】:

  • 你可以使用 calloc 或 memset 代替初始化循环,顺便说一句。
  • @Bobby Sacamano 使用 calloc or memset 将依赖于具有全 0 位模式的 NULL - C 未指定的东西 - 尽管 calloc or memset 通常会很好。 for() 循环更加明确和具有示范性,尤其是对学习者而言——就像我们所有人一样。
  • @chux 我在 ISO9899 n1256 pg 47 中发现了这一点“值为 0 的整数常量表达式,或转换为 void * 类型的表达式称为空指针常量。55) 如果为空指针常量转换为指针类型,生成的指针,称为空指针,保证与指向任何对象或函数的指针比较不相等。”。一个体系结构可以让所有 0 位模式不等于 0 吗?不过,不和初学者一起打代码高尔夫可能是一个不错的选择。
  • @Bobby Sacamano 确实,int *a = NULL;int *b = 0 都会将指针分配给“空指针”,a == b 是真的。然而,打印 2 个指针可能会导致不同的输出,因为系统可能有超过 1 个空指针值。注意:NULL 是一个“空指针常量”。
  • @Bobby Sacamano “架构是否可以全部 0 位模式不等于 0?”是的所有类型,除了unsigned char。当然,这样的系统不在主要轨道上——但标准允许。大洞是填充位,系统可以以新颖的方式使用它。建议搜索 SO - 确保已解决。
【解决方案2】:
 **hashtable = malloc(Node_size * htsize);

这是取消引用哈希表两次,然后将其分配给 malloc 返回的指针。您应该将指针哈希表分配给 malloc 返回的指针。

例如

     hashtable = malloc(Node_size * htsize);

编辑:我重读了您的代码。您不应该将哈希表声明为数组。数组的存储时长是本地的;一旦函数返回,数组就会被释放。无论如何你只返回第一个元素,所以它可能只是一个错字。

你也应该只是return hashtable,而不是return *hashtable

更新:您更改了为哈希表数组的每个元素分配一个节点的方法,但您只返回该数组的第一个元素。

Node **hashtable[htsize]; 应改为Node **hashtable; 您不能返回具有自动存储类的数组,因此将其声明为数组似乎是一个错误。

此外,您只返回此数组的第一个元素,因此这会导致内存泄漏return *hashtable 等效于返回hashtable[0]

我认为这是您正在寻找的行为:

Node **ht_create(void)
{
   Node **hashtable;

   if(htsize < 1)
   {
       printf("Error: please enter adequate size for hashtable");
       return NULL;
   }

   hashtable = malloc(htsize * sizeof(Node*)) //allocate the array
   if(hashtable  == NULL )
   {
       printf("Error: could not allocate memory for hashtable");
       return NULL;
   }


   for (int i = 0; i < htsize; i++)
   {
       hashtable[i] = malloc(sizeof(Node)); //allocate each node in the array
       if(hashtable[i] == NULL) //you have to null check these too
       {
           printf("Error: could not allocate memory for hashtable");
           return NULL;
       }
   }

   return hashtable; //return the array of node pointers
}

如果分配失败,您可能应该取消分配所有其他节点,除非您此时无论如何都要退出程序。您可以随心所欲地计算出来,因为这取决于您如何实现其余代码。

【讨论】:

  • 删除双指针时,出现编译错误:“Array Type 'Node **[htsize]' is not assignable.”
  • @chux 是的,我错过了。将其声明为数组似乎也是一个错误。
  • 我稍微编辑了代码以使用 for 循环为表中的每个节点分配,但现在我得到了自己的“错误:无法为哈希表分配内存”错误我在函数中拥有的
  • 这也行得通,谢谢伙计,如果我可以投票给你们两个我会的,但我没有足够的声誉。在过去的 30 分钟里,我从你和 @chux 那里学到了更多关于 malloc 和哈希表的知识,而不是我在一个半小时的讲座中学到的。再次感谢。
猜你喜欢
  • 2011-03-07
  • 2020-06-05
  • 1970-01-01
  • 2021-03-04
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多