【问题标题】:C - Too much memory allocated with mallocC - 使用 malloc 分配的内存过多
【发布时间】:2017-04-08 10:59:13
【问题描述】:

我正在为学校做一个项目,我必须创建二叉树并将其放入动态数组中。 我指定我正在使用 GCC(GNU 编译器)在 Windows 上工作。

typedef struct s_node * TN;
struct s_node {
    char * chain; //Name of the tree
    int occ; //Number of occurences
    int ht; //Tree's height
};
typedef struct s_binary_tree * TBA;
struct s_binary_tree {
    TN root;
    TBA stl; //Sub Tree Left
    TBA str; //Sub Tree Right
};

首先我使用 malloc() 分配内存来创建一个包含 x 平方二叉树的数组,然后我为二叉树分配内存。

TBA create_Binary_Tree(char * chain, int occ, int number_letters) {
    TBA tree = malloc(sizeof(TBA));
    tree->root = malloc(sizeof(TN));
    tree->root->chain = malloc(sizeof(char) * (number_letters + 1)); //+1 for the '\0'

    *(tree->root->chain) = '\0';
    strcpy(tree->root->chain,chain);
    tree->root->occ = occ;
    tree->root->ht = 1;

    tree->stl = NULL;
    tree->slr = NULL;

    return tree;
}

TBA * create_Array_Binary_Tree(char * fileName) {
    FILE * file;
    file = fopen(fileName,"r");
    if(!file) {
        exit(EXIT_FAILURE);
    }

    int number_letters;
    fscanf(file,"%d",&number_letters); //number_letters is the number of square that I want to allocate
    TBA * arr = malloc(sizeof(TBA) * number_letters);
    char * letter = malloc(sizeof(char) * 256);
    int occ, i;


    for(i = 0; i < number_letters; i++) { //number_letters = 1 in our example
        fscanf(file,"%s %d",letter,&occ);
        *arr = create_Binary_Tree(letter,occ,number_letters);
    printf("--Adr = %p--\n"arr); //Print the adress
        arr++;
    }
    arr -= i; //Reset the arr pointer

    fclose(file);

    return arr;
}

我的问题是当我计算数组的大小时,程序告诉我数组大小是 x + 38 平方。

int size_Array_Binary_Tree(TBA * arr) {
    int sz_arr = 0;

    while(*arr != NULL) {
printf("-T = %d\tAdr = %p-\n",sz_arr,arr); //Print the adress
    sz_arr++;
    arr++;
}

return sz_arr;
}

终端:

--Adr = 0000000000951430-- //1 square allocated
-T = 0  Adr = 0000000000951430- //The square allocated
-T = 1  Adr = 0000000000951438- //?
-T = 2  Adr = 0000000000951440- //?
-T = 3  Adr = 0000000000951448- //...
-T = 4  Adr = 0000000000951450-
-T = 5  Adr = 0000000000951458-
-T = 6  Adr = 0000000000951460-
-T = 7  Adr = 0000000000951468-
-T = 8  Adr = 0000000000951470-
-T = 9  Adr = 0000000000951478-
-T = 10 Adr = 0000000000951480-
-T = 11 Adr = 0000000000951488-
-T = 12 Adr = 0000000000951490-
-T = 13 Adr = 0000000000951498-
-T = 14 Adr = 00000000009514A0-
-T = 15 Adr = 00000000009514A8-
-T = 16 Adr = 00000000009514B0-
-T = 17 Adr = 00000000009514B8-
-T = 18 Adr = 00000000009514C0-
-T = 19 Adr = 00000000009514C8-
-T = 20 Adr = 00000000009514D0-
-T = 21 Adr = 00000000009514D8-
-T = 22 Adr = 00000000009514E0-
-T = 23 Adr = 00000000009514E8-
-T = 24 Adr = 00000000009514F0-
-T = 25 Adr = 00000000009514F8-
-T = 26 Adr = 0000000000951500-
-T = 27 Adr = 0000000000951508-
-T = 28 Adr = 0000000000951510-
-T = 29 Adr = 0000000000951518-
-T = 30 Adr = 0000000000951520-
-T = 31 Adr = 0000000000951528-
-T = 32 Adr = 0000000000951530-
-T = 33 Adr = 0000000000951538-
-T = 34 Adr = 0000000000951540-
-T = 35 Adr = 0000000000951548-
-T = 36 Adr = 0000000000951550-
-T = 37 Adr = 0000000000951558-
-T = 38 Adr = 0000000000951560- //?

返回的大小应该是 1,但它返回 39。 你能帮帮我吗?

编辑:我从类型中删除了指针并调整了其余部分,但问题仍然存在。

typedef struct s_node TN;
struct s_node {
    ...
};

typedef struct s_binary_tree TBA;
struct s_binary_tree {
    TN * root;
    TBA * stl;
    TBA * str;
};

TBA * create_Binary_tree(...) {
    TBA * tree = malloc(sizeof(TBA));
    tree->root = malloc(sizeof(TN));
    ...
    return tree;
}

TBA ** create_Array_Binary_Tree(...) {
    ...
    TBA ** arr = malloc(sizeof(TBA *) * number_letters);
    ...
    for(i = 0; i < number_letters; i++) {
        ...
        arr[i] = malloc(sizeof(TBA));
        arr[i] = create_Binary_Tree(...);
        ...
    }
    ...
    return arr;
}

有什么想法吗?

【问题讨论】:

  • TBA tree = malloc(sizeof(TBA)); 显然坏了。左侧(声明变量tree)和右侧(sizeof 的参数)具有相同的类型。通常这看起来像T *x = malloc(sizeof (T))(左侧有一个指针)。不要将指针隐藏在 typedef 后面。
  • sizeof (char) 定义为 1。

标签: c arrays memory memory-management


【解决方案1】:

这个程序有几个错误:

TBA create_Binary_Tree(char * chain, int occ, int number_letters) {
    TBA tree = malloc(sizeof(TBA));
    ...
}

TBA 是一个指向结构的指针。当您分配 sizeof(TBA) 时,您要求分配 pointer 所需的尽可能多的内存,即 4 字节(32 位)或 8 字节(64 位)。您想为 struct 分配空间:

TBA tree = malloc(sizeof(struct s_binary_tree));

同样的问题:

tree->root = malloc(sizeof(TN));

应该是:

tree->root = malloc(sizeof(struct s_node));

实际上只有TBA * arr = malloc(sizeof(TBA) * number_letters); 是正确的。

Avoid strcpy.

不要像arr -= i; 那样做凌乱的指针算术,而是使用第二个变量来存储原始指针或要修改的指针。

你不是 NULL 终止 arr。分配后,里面可能有垃圾。如果您依赖它作为哨兵,最好确保用 NULL 填充它:

memset(arr, 0, sizeof(TBA) * number_letters);
// Or use `calloc`, `bzero`, ...

这可能是你的size_Array_Binary_Tree 给你一个奇怪的结果的原因。

【讨论】:

  • 避免strcpy 可能是一个好主意,但您链接到的问题是关于strncpy,永远不应该使用(并且那里的几个答案和cmets 同意)。 strncpy 不是 strcpy 的更安全版本。
  • 技术上 memsetting arr 到所有位为零不需要生成空指针。 C 不要求空指针具有特定的表示形式(不同类型的空指针可以设置不同的位)。
  • @melpomene:你对strncpy 的看法是正确的,应该选择一个更好的问题/答案……不过,不能很快找到。关于空指针:你也是对的,但这对于新手程序员来说无关紧要,因为它在典型程序员接触的所有机器上都是零位。如果您愿意,请将其替换为 for (int i = 0; i &lt; number_letters; ++i) { arr[i] = 0; }
  • 我更改了类型,但问题仍然存在。
  • @jeanbrick:你是否也初始化了arr 的内存(使用memset 或我在对melpomene 的评论中提到的for 循环)?
猜你喜欢
  • 2012-10-10
  • 2020-11-01
  • 2021-06-15
  • 2020-12-14
  • 1970-01-01
  • 2015-11-09
  • 2013-11-14
  • 2015-02-11
相关资源
最近更新 更多