【问题标题】:Allocating memory for structs and its members为结构及其成员分配内存
【发布时间】:2017-03-27 13:21:32
【问题描述】:

我只是进入结构并为它们分配内存。现在我有一些示例代码,它们可以像下面的“Learn C The Hard Way”一样开箱即用

struct Person {
    char *name;
    int age;
    int height;
    int weight;
};

struct Person *Person_create(char *name, int age, int height,
        int weight)
{
    struct Person *who = malloc(sizeof(struct Person));
    assert(who != NULL);

    who->name = strdup(name);
    who->age = age;
    who->height = height;
    who->weight = weight;

    return who;
}

这就是我的理解。在函数*Person_create 中,指针*who 接收大小为struct Person 的内存块的地址。 Struct Person 有 4 个成员,一个指向字符串的指针和三个整数。由于指针*who 的类型为struct Person,据我所知,它应该知道它具有这些成员。

现在我尝试用一​​些自己的代码创建类似的东西。不幸的是,我在尝试为即将到来的变量 int age 扫描 f() 整数时遇到了段错误。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>

#define STRINGLENGTH 30
struct Person {
    char *name;
    char *food;
    int age;
    float height;
};

struct Person *createPerson(FILE *file){
    struct Person *who = malloc(sizeof(struct Person));
    assert(who != NULL);

    who->name = malloc(sizeof(who->name)*STRINGLENGTH);
    who->food = malloc(sizeof(who->food)*STRINGLENGTH);

    printf("What is the name of the person?\n");
    scanf("%29s",who->name);
    fprintf(file,"Name:%s\n",who->name);

    printf("What food do you eat?\n");
    scanf("%29s",who->food);
    fprintf(file,"Food:%s\n",who->food);

    printf("How old are you?\n");
    scanf("%d",who->age);
    fprintf(file,"Age:%d\n",who->age);

    printf("Whats your height?\n");
    scanf("%f",who->height);
    fprintf(file,"Height:%f\n",who->height);

    return who;
}

void freePerson(struct Person *who){
    free(who->name);
    free(who->food);
    free(who);
}

int main(int argc, char *argv[]){

    FILE *file;

    if((file = fopen("person.txt","a")) == NULL){
        perror(NULL);
        return EXIT_FAILURE;
    }

    printf("Creating a person...\n");

    struct Person *newPerson = createPerson(file);

    freePerson(newPerson);

    fclose(file);

    return EXIT_SUCCESS;
}
  • 那么导致问题的差异是什么?
  • 我也需要单独 malloc 成员吗?
  • 是不是因为示例代码中已经设置了变量?

【问题讨论】:

  • 这是选项 4 - 你没有正确调用 scanf
  • 和往常一样,valgrind 就是答案
  • [不是原因] who-&gt;name = malloc(sizeof(who-&gt;name)*STRINGLENGTH); -->> who-&gt;name = malloc(STRINGLENGTH); :: 你想分配 STRINGLENGTH 个字符(不是指针)
  • 顺便说一句,请注意您在Learn C The Hard Way 中提供的示例显示了对断言的严重误用。断言是非常错误的检查合理的运行时错误的工具。它们用于检查 programming 错误。如果您的程序曾经遇到断言失败,这意味着您的程序是错误的。此外,根据您构建代码的方式,甚至可能不会在运行时检查断言的条件,因此您不能将它们用于强制性的函数结果检查。
  • 感谢您的宝贵建议!

标签: c pointers struct malloc


【解决方案1】:

您会收到段错误,因为您没有传递年龄字段的地址。相反,您将 scanf 的不确定值复制为地址。

一个简单的本地修复:

scanf("%d",&(who->age));
fprintf(file,"Age:%d\n", who->age);

当我们讨论这个主题时,您为字符串分配的内存超出了您的预期。 sizeof(who-&gt;name) 是指针的大小,不小于它所指向的char 的大小。更重要的是,保证sizeof(char) == 1。所以字符串的分配可以完全简化:

who->name = malloc(STRINGLENGTH);

【讨论】:

  • who-&gt;name = malloc(sizeof(*(who-&gt;name)*STRINGLENGTH); 也可以吗?
  • @ThomasChristopherDavies - 会的。但是您希望角色类型发生变化吗?否则,我会主张删除一个归结为 1 的表达式。但这取决于你 :)
  • @ThomasChristopherDavies - 防御用户输入非常聪明。防止滥用 API 也是非常聪明的。但是恕我直言,对语言规范保证的东西进行防御是愚蠢的 :) 如果你不能相信标准中的 那个 事实,为什么还要相信任何东西呢?
  • @ThomasChristopherDavies - 我并不是说这很糟糕(这就是为什么我问关于字符类型的主要问题)。做你觉得舒服的事。如果冗长的东西让你记住,请记住它:)
  • 这不是“懒惰”。考虑到所有约束和选项,它是关于明确并选择“最佳”构造。那么malloc(sizeof(*(who-&gt;name)*STRINGLENGTH); 虽然不懒,但属于混淆C。
猜你喜欢
  • 2012-08-27
  • 2022-11-07
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 2015-12-15
  • 1970-01-01
相关资源
最近更新 更多