我有一个结构malloc()'d,在使用它们之后,我想释放()它,但我的程序冻结在这里。谁能告诉我,我做错了什么?
这是我的代码:
struct data
{
char *filename;
char *size;
};
//primarypcs is a long type variable
struct data *primary = (struct data *)malloc( primarypcs * sizeof( struct data ) );
memset( primary, 0, sizeof(struct data *) * primarypcs );
...
...
...
for ( i = 0; i < primarypcs; i++ )
{
free( primary[i].filename ); //<----my program freezes here
free( primary[i].size ); //<----or here
}
free( primary );
提前致谢!
kampi
编辑:
如何正确地将malloc内存用于文件名和大小?
EDIT2:
抱歉,但我很着急,我没有告诉你所有你需要的信息。现在让我这样做:)基本上,我想创建一个应用程序,它获取两个给定驱动器/文件夹的文件列表,然后比较它们。我想(并且仍然这样),最简单的方法是,当我将文件名及其大小存储在如上所述的结构中时。所以我必须动态分配内存(我认为这就是他们所说的)文件名和大小以及结构的内容。
答案 0 :(得分:7)
你没有展示整个代码,很多东西都可能出错,但是一个错误已经很明显了。这条线
memset( primary, 0, sizeof(struct data *) * primarypcs );
没有做你认为它正在做的事情。由于sizeof
中的类型错误,它不会将整个数组归零。它很可能应该是
memset( primary, 0, sizeof(struct data) * primarypcs );
请注意*
下的sizeof
。由于此错误,数组中的大多数指针都包含垃圾作为其初始值。如果你没有在省略的代码中将它们设置为有意义的东西,那么对free
的调用将接收垃圾参数并失败。
通常,为了减少此类错误的可能性,最好避免在程序中提及类型名称,声明除外。既然你的问题被标记为C ++(即使它肯定看起来像C),也不可能摆脱malloc
上的类型转换,但除此之外我会说以下看起来更好
struct data *primary = (struct data *) malloc( primarypcs * sizeof *primary );
memset( primary, 0, primarypcs * sizeof *primary );
而且,作为旁注,如果您的代码是C ++,那么您可以以更加优雅,紧凑和便携的方式获得相同的结果
data *primary = new data[primarypcs]();
当然,在这种情况下,您必须使用适当的C ++功能而不是free
来释放内存。
答案 1 :(得分:3)
如何分配结构中的字符串?如果将它们静态分配给常量,那么不要以那种方式释放它们,并且所需要的只是free (primary);
释放一些不是malloc的东西会让堆管理员心脏癫痫发作。
如果字符串指针是由malloc()或calloc()设置的,那就是正确的方法。
答案 2 :(得分:2)
如果你在C ++中这样做,你(几乎可以肯定)不应该使用类似的东西:
data *primary = new data[primarypcs]();
相反,你应该使用类似的东西:
struct data {
std::string filename;
std::string size;
};
std::vector<data> primary(primarypcs);
在这种情况下,您通常可以更简单地处理内存管理:在需要的范围内定义向量,当它超出范围时,内存将自动释放。
在C ++中使用数组new(如new x[y]
)是你最好没有的。曾几何时(15年前左右)它几乎是唯一可用的工具,所以它的(勉强)使用几乎是不可避免的 - 但是那一天已经过去很长时间了,而且它已经过去10年了,因为它确实很好使用它的原因。
由于不可避免地会发表评论“除了实现像矢量这样的东西”之外,我会指出,不,即使你实现了矢量你不使用数组新 - 你(间接地,通过分配器) )使用::operator new
分配原始内存,使用新的位置在该内存中创建对象,使用显式dtor调用来销毁对象。
答案 3 :(得分:1)
正如其他人所说,你所展示的片段中有两个明显错误的东西:
filename
和size
成员分配内存,memset()
来电使用了错误的尺寸。您的memset()
来电可以通过以下方式简化和纠正:
memset(primary, 0, primarypcs * sizeof *primary);
您的代码还有另一个微妙的问题:C标准并不保证all-bits-zero是空指针常量(即NULL),因此memset()不是设置指针的正确方法NULL
。做你想做的便携方式是:
size_t i;
for (i=0; i < primarypcs; ++i) {
primary[i].filename = NULL;
primary[i].size = NULL;
}
要为filename
和size
分配内存,这取决于您的需求。假设您确定filename
需要n
字节,size
需要m
。然后,你的循环变成这样的东西:
size_t i;
for (i=0; i < primarypcs; ++i) {
size_t n, m;
/* get the values of n and m */
primary[i].filename = malloc(n * sizeof *primary[i].filename);
primary[i].size = malloc(m * sizeof *primary[i].size);
}
如果你愿意,你可以省略上面的sizeof *primary[i].filename
和sizeof *primary[i].size
的乘法:C保证sizeof(char)
是1.我写了上面的完整性和{{ {1}}和filename
更改类型。
另请注意,如果size
是一个长度为filename
的字符串,那么您需要k
个字节,因为终止(k+1)
(所以{{1上面)。
如果我猜错,您希望0
存储相应n == k+1
的长度?如果是这种情况,size
不应该是filename
而是size
。但由于我不知道你打算如何使用char *
和size_t
,我不确定。
请务必检查filename
的返回值。它会因失败而返回size
。为简单起见,我省略了上述代码中的检查。
您的帖子也被标记为C ++,所以如果您愿意使用C ++,也可以使用C ++解决方案。
答案 4 :(得分:0)
使用free (primary);
替换代码底部的for循环应该有效。
答案 5 :(得分:0)
这是因为您没有为filename
和size
明确分配内存。因此,尝试执行free( primary[i].filename );
或free( primary[i].size );
会调用未定义的行为。
只需free(primary)
即可。
修改强>:
这个问题已被标记为C ++。因此,C ++的方法是使用new
代替malloc
用于用户定义的类型。
对于new
和malloc
之间的差异,请查看this.
在 C ++ 中,您只需要编写
data *primary = new data[primarypcs](); //() for value initialization
答案 6 :(得分:0)
这解决了你在memset中的问题,这会给你带来各种各样的问题。
memset( primary, 0, sizeof(struct data) * primarypcs );
简而言之,您在“主要”结构的末尾留下了未初始化的内存。
答案 7 :(得分:0)
您未能对整个数组进行memset,导致释放垃圾内存指针。使用calloc而不是malloc / memset来避免这个错误:
struct data *primary = calloc(primarypcs, sizeof(struct data));
这两者都分配并清除内存。
如果您还要初始化所有struct data
条目:
for (i = 0; i < primarypcs; ++i) {
primary[i].filename = malloc(...);
primary[i].size = malloc(...);
}
(你没有描述大小的文件名是什么,所以我把...留下来让你填写)。