如何释放()一个正确的malloc()结构?

时间:2010-02-02 02:26:58

标签: c pointers free malloc

我有一个结构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:

抱歉,但我很着急,我没有告诉你所有你需要的信息。现在让我这样做:)基本上,我想创建一个应用程序,它获取两个给定驱动器/文件夹的文件列表,然后比较它们。我想(并且仍然这样),最简单的方法是,当我将文件名及其大小存储在如上所述的结构中时。所以我必须动态分配内存(我认为这就是他们所说的)文件名和大小以及结构的内容。

8 个答案:

答案 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)

正如其他人所说,你所展示的片段中有两个明显错误的东西:

  1. 您不为刚刚分配的结构的filenamesize成员分配内存,
  2. 您的memset()来电使用了错误的尺寸。
  3. 您的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;
    }
    

    要为filenamesize分配内存,这取决于您的需求。假设您确定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].filenamesizeof *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)

这是因为您没有为filenamesize明确分配内存。因此,尝试执行free( primary[i].filename );free( primary[i].size );会调用未定义的行为

只需free(primary)即可。

修改

这个问题已被标记为C ++。因此,C ++的方法是使用new代替malloc用于用户定义的类型。

对于newmalloc之间的差异,请查看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(...);
}

(你没有描述大小的文件名是什么,所以我把...留下来让你填写)。