Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何释放一个malloc()';d结构正确吗?_C_Pointers_Free_Malloc - Fatal编程技术网

如何释放一个malloc()';d结构正确吗?

如何释放一个malloc()';d结构正确吗?,c,pointers,free,malloc,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 ) ); mems

我有一个结构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 );  
struct数据
{  
字符*文件名;
字符*大小;
};   
//primarypcs是一个长类型变量
结构数据*primary=(结构数据*)malloc(primarypcs*sizeof(结构数据));
memset(primary,0,sizeof(struct data*)*primarypcs);
...
...
...
对于(i=0;ifree(primary[i].filename);//结构中的字符串是如何分配的?如果它们是静态分配给常量的,那么就不要这样释放它们,所需要的只是
free(primary);
释放一些不是malloc的东西会让堆管理器心跳加速


如果字符串指针是由malloc()或calloc()设置的,这是正确的方法。

您并不是在展示整个代码,其中可能会出现很多错误,但有一个错误已经很明显。行

memset( primary, 0, sizeof(struct data *) * primarypcs );   
没有执行您认为它正在执行的操作。由于
sizeof
中的类型错误,它没有将整个数组归零。很可能是这样

memset( primary, 0, sizeof(struct data) * primarypcs );   
请注意,在
sizeof
下没有
*
。由于此错误,数组中的大多数指针的初始值都包含垃圾。如果在省略的代码中未将其设置为有意义的值,则对
free
的调用将接收垃圾参数并失败

一般来说,为了减少这种错误的机会,最好避免在程序中提及类型名称,除非在声明中。因为问题是标记C++(即使它看起来像C),所以不可能在MalOC><代码>上删除类型转换,但否则我会说下面看起来更好。
struct data *primary = (struct data *) malloc( primarypcs * sizeof *primary );   
memset( primary, 0, primarypcs * sizeof *primary );   

,作为一个旁注,如果你的代码是C++的,你可以得到一个更优雅、紧凑和可移植的方式

的相同结果。
data *primary = new data[primarypcs]();

当然,在这种情况下,您必须使用适当的C++功能来代替内存,而不是<代码>免费< /COL> .< /P> < P> >用代码>自由(主)替换代码底部的for循环。
应该可以工作。

这是因为您没有显式地为
文件名和
大小分配内存。因此尝试执行
释放(主[i].filename);
释放(主[i].size);
将调用未定义的行为

只要
免费(主要)
就足够了

编辑

这个问题已经被标记为C++。因此C++的方式是使用<代码>新< /代码>代替用户定义的类型< <代码> MalOC 。 有关
new
malloc
之间的差异,请查看

C++中,只需编写

 data *primary = new data[primarypcs](); //() for value initialization

这修复了memset中的问题,它为您带来了各种各样的问题

memset( primary, 0, sizeof(struct data) * primarypcs );  

简而言之,在“主”结构的结尾处留下未初始化的内存。

如果你在C++中这样做,你(几乎可以肯定)不应该使用类似:

data *primary = new data[primarypcs]();
相反,您应该使用以下内容:

struct data {
    std::string filename;
    std::string size;
};

std::vector<data> primary(primarypcs);
struct数据{
std::字符串文件名;
std::字符串大小;
};
std::主要病媒(primarypcs);
在这种情况下,通常可以更简单地处理内存管理:在需要的范围内定义向量,当它超出范围时,内存将自动释放

在C++中使用数组new(比如<代码>新x[y] < /COD>)是一个更好的方法。一次(15年前),它几乎是唯一可用的工具,因此它的(勉强)使用几乎是不可避免的——但那一天已经过去了,而且自从使用它确实有一个很好的理由以来,已经过去了10年。
由于不可避免地会有关于“除了在实现类似vector的东西时”的评论,我要指出,不,即使在实现vector时,也不使用array new——您(间接地,通过分配器)使用
::operator new
分配原始内存,placement new在该内存中创建对象,显式dtor调用销毁对象。

正如其他人所说,您显示的代码片段中有两个明显错误的地方:

  • 您不为刚刚分配的结构的
    filename
    size
    成员分配内存
  • 您的
    memset()
    调用使用了错误的大小
  • 您的
    memset()
    调用可以通过以下方式简化和更正:

    memset(primary, 0, primarypcs * sizeof *primary);
    
    代码中还有一个微妙的问题:C标准不能保证所有的零位都是null指针常量(即null),因此memset()不是将指针设置为
    null
    的正确方法

    size_t i;
    for (i=0; i < primarypcs; ++i) {
        primary[i].filename = NULL;
        primary[i].size = NULL;
    }
    
    如果需要,您可以省略与上面的
    sizeof*primary[i].filename
    sizeof*primary[i].size
    的乘法:C保证
    sizeof(char)
    为1。为了完整性以及
    filename
    size
    更改类型的情况,我编写了上面的代码

    另外,请注意,如果
    filename
    是一个长度为
    k
    的字符串,则需要
    (k+1)
    字节,因为上面的
    0
    (因此
    n==k+1

    如果我猜猜看,您希望
    size
    存储相应的
    filename
    的长度?如果是这样,
    size
    不应该是
    char*
    而是
    size\u t
    。但是因为我不知道您打算如何使用
    filename
    size
    ,我不确定

    确保检查
    malloc()
    的返回值。如果失败,它将返回
    NULL
    。为了简单起见,我在上面的代码中省略了检查


    你的帖子也被标记为C++,所以如果你愿意使用C++,也有一个C++解决方案。

    你不能对整个数组结果进行内存设置。
    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);
    }
    
    struct data *primary = calloc(primarypcs, sizeof(struct data));
    
    for (i = 0; i < primarypcs; ++i) {
        primary[i].filename = malloc(...);
        primary[i].size = malloc(...);
    }