C内存分配:结构中结构中的固定长度数组

时间:2016-08-26 12:48:00

标签: c arrays memory-management struct memory-leaks

编辑[2016-08-26-001]:我已经更正了评论中指出的错误。正如我在下面提到的,我很快就抓住并修改了一些代码来解释这个问题,抱歉:(

以下是我原始来源的修改后的摘录(仍然是一团糟!!!)但应该这样做:

#define STORAGE_LIMIT_NAME  64
#define DB_INIT_ENTRIES     100

struct entry {
        char fname[STORAGE_LIMIT_NAME];
        char sname[STORAGE_LIMIT_NAME];
};

struct database {
        struct entry *data;
        unsigned int entries;
        unsigned int entrysz;
};

struct database mydb;

mydb.entrysz = sizeof(struct entry);
mydb.entries = DB_INIT_ENTRIES;
mydb.data = malloc(mydb.entrysz * DB_INIT_ENTRIES);

free(mydb.data);

我需要知道以下内容:

1)我做得对吗?也就是说,内存所有是否已分配给堆并因此被释放?我不希望内存泄漏。

2)是否有更优雅的解决方案,不会使事情过于复杂,仍然可以轻松限制名称长度?此外,它最好是快速的。

很抱歉,如果以前曾经问过这个问题,我已经浏览过这个网站和谷歌,但我发现其他人偶尔会做一些模糊相似的事情,同时提出完全不同的问题。到目前为止,我在网上看过的任何学习指南都没有包含这个内容。我需要理解这个如果我想作为程序员变得更好而且我是自学成才的,所以我没有一个讲师可以参加。顺便说一句,欢迎任何链接到良好的免费C(非C ++)学习材料。非常感谢。

3 个答案:

答案 0 :(得分:1)

1)是的,这里的代码为DB_INIT_ENTRIES结构数组分配了足够的空间,每个结构的大小为sizeof(struct entry)个字节:

mydb.entrysz = sizeof(struct entry);
mydb.entries = DB_INIT_ENTRIES;
mydb.data = malloc(mydb.entrysz * DB_INIT_ENTRIES);

此调用然后释放整个数组:

free(mydb.data);

您未展示的是如何访问分配的数组中的每个结构:

struct entry *  entp;     // Entry pointer
entp = &mydb.data[i];     // Where 0 <= i < mydb.entries


正切

作为编程风格的问题(与你的问题无关),我更喜欢明确表示字符数组旨在通过向显式+1添加显式#define STORAGE_LIMIT_NAME 63 struct entry { char fname[STORAGE_LIMIT_NAME+1]; char sname[STORAGE_LIMIT_NAME+1]; }; 来保存以空字符结尾的字符串。数组大小,即:

+1

显式STORAGE_LIMIT_NAME清楚地表明名称数组以额外的NUL字符结尾。它还使entry根据字符定义最大名称长度,而不是其分配大小。


[*] BTW,{{1}}曾经是早期C中的保留关键字,但在1988年该语言标准化时被删除。

答案 1 :(得分:1)

是的,没有泄漏。我鼓励你熟悉Valgrind,它通常用于内存泄漏。

另外,我建议总是将malloc强制转换为指定的数据类型!不要将它留给编译器。

并且,是的,我同意上述两个答案,以便在Null字符的空格处有+1个字节。

奖金材料:

熟悉GDB,因为它可以为许多程序员节省大量时间。它是一个很棒的调试器,您可以确保您的代码按预期运行/执行。我正在为GDB和Valgrind附上一份备忘单。

GDB

Valgrind

答案 2 :(得分:0)

1)是的,没有泄漏 您的DATE分配在堆malloc()个字节中,可以将其抽象为mydb.entrysz * DB_INIT_ENTRIES的数组struct entry

DB_INIT_ENTRIES知道在free(mydb.data)上动态分配了多少字节,因此它释放了所有这些字节。

另外,你应该在free()之后将mydb.data设置为NULL:
Setting variable to NULL after free

2)如果你的mydb.data存储二进制数据,我会像你一样完成,但如果名字是c字符串,我会在每个数组的结尾'\ 0'中再分配一个字符:

struct entry

这种方式struct entry { char fname[STORAGE_LIMIT_NAME+1]; char sname[STORAGE_LIMIT_NAME+1]; }; 表示您可以存储的字节数。