【问题标题】:C array of structure (exception thrown)C 结构数组(抛出异常)
【发布时间】:2019-09-05 16:51:08
【问题描述】:

我创建了一个 Human 结构数组,其中包含 char *name。

我使用这样的功能:

Human *createHuman(char *name){
    Human *h = malloc(sizeof(Human));
    h->name = strdup(name);
    return h;
}

我已经测试过这个功能,它工作得很好,但是当我像这样使用它时我的问题就开始了:

void gen_Humans(Human array[MAX], int n){
    //n == max;
    for (int i = 0; i<n; i++){
        char *name = gen_name_function_used_before_WORKING();
        array[i] = *createHuman(*name);
    }
    …
}

正如我所说,如果我生成一个人类,它就可以正常工作。 我调试了我的代码,当我到达strdup(name) 时,它给了我这个:

my error: Exception thrown at 0x53DCF6E0 (ucrtbased.dll) in project.exe:
0xC0000005: Access violation reading location 0x00000070.

我正在使用 VS 2017 企业版。

【问题讨论】:

  • 这不包括minimal reproducible example(您的createHuman 函数不会返回任何内容)
  • 是的 n==max 和 createhuman 返回 h,感谢 cmets! :)
  • 你创造人类的方式很奇怪。 1)您正在发送一个已经分配的人体结构数组,而不是一个指向人体结构的指针数组。 2)你没有在循环中正确使用createHuman,它应该是createHuman(name)而不是createHuman(*name) 3)然后你试图复制一个malloc'd人(从createHuman返回)复制到数组(已经分配)这将造成内存泄漏,因为您没有存储 malloc 分配的指针以便以后释放它们
  • 你得到了接近空指针异常的东西——你访问的是地址 112 (0x70) 而不是 0 (0x00),仅此而已。仔细查看gen_name_function_used_before_WORKING() 的返回值,因为它很可能不起作用。另外,您正在泄漏内存; RHS 上的*createHuman() 意味着您丢失了指向结构和重复名称的指针。您需要从指针中捕获gen_name_function_used_before_WORKING() 函数的返回值,然后复制它,然后释放名称组件和指向的结构。
  • 这个问题回答了吗?

标签: c arrays string struct strdup


【解决方案1】:

当调用你的函数 createHuman 时,你传递的是你名字的值:

array[i] = *createHuman(*name);

在构建此应用程序时,我收到以下编译器警告 (GCC):

warning: passing argument 1 of 'createHuman' makes pointer from integer without a cast

由于您的函数createHuman 需要名称的地址,因此您还应该传递地址。例如:

array[i] = *createHuman(name);

【讨论】:

    【解决方案2】:

    添加到@MortizSchmidt 的答案:

    • 您没有检查malloc() 的结果。即使失败的可能性很小,您也应该这样做。
    • 您正在泄漏内存 - 因为您从未释放 malloc()ed 内存,也没有将指针保留在任何地方。请记住,C 不像 Java - 赋值不是引用的赋值。
    • 请注意,函数签名中的MAX 指示符没有任何作用。该参数是一个 int*,无论您如何编写:int* array、int array[] 或 int array[MAX]。

    实际上,为什么还要分配 Human 结构而不仅仅是为字符串分配空间?

    struct Human createHuman(char *name){
        if (name == NULL) {
            struct Human h = { NULL };
            return h;
        }
        struct Human h = { strdup(name) };
        if (h.name == NULL) { /* handle error here */ }
        return h;
    }
    
    void gen_Humans(Human array[MAX], int n){
        for (int i = 0; i < n; i++) {
            char *name = gen_name_function_used_before_WORKING();
            array[i] = createHuman(name);
        }
        …
    }
    

    这具有将Human 中name 之后的所有字段初始化为0 的额外好处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 2014-04-16
      • 2015-05-07
      • 2022-01-16
      • 2019-03-11
      • 2023-03-11
      相关资源
      最近更新 更多