重复分配内存而不释放它

时间:2018-07-31 04:37:08

标签: c pointers function-pointers free dynamic-memory-allocation

以下代码显示了一个示例,该示例重复分配内存而没有先调用free。相反,它将在循环后释放**sign

#include <stdio.h>
#include <stdlib.h>

float ** fun(int nloc)
{
    float **sign;
    int i,nt=100,it,k;
    sign=(float **)calloc(nloc,sizeof(float *));
    for (i=0;i<nloc;i++)
        sign[i] = (float *)calloc(nt,sizeof(float *));

    for (it=0;it<nt;it++){
        for (k=0;k<nloc;k++){
            sign[k][it]=it*0.2;
        }
    }
    return sign;
}


int main(int argc, char *argv[])
{
    int i,isrc,n=3,nloc=1;
    float **sign=NULL;
    for (isrc=0;isrc<n;isrc++){
        sign = fun(nloc);
    }
    for (i=0;i<nloc;i++){
        free(sign[i]);
    }
    free(sign);
    exit(0);
}

这是正确的代码段。我的问题是:为什么在每次迭代中都可以为一个指针分配内存而不必先释放它是合法的?

[补充信息]:

大家好,我认为有一种情况我们无法在循环中free进行存储。如果buffer=pp是在循环外部定义的,例如:

float *buffer, *p;
/* Elements of p calculated */
for (...){
    /* allocate memory for **buffer */    
    buffer = p;
    free(buffer)
    /* if free here will cause p lost */
}

如果在每个循环结束时有空闲的buffer,则可能会由于pbuffer共享相同的内存地址而导致p丢失。

3 个答案:

答案 0 :(得分:4)

  

为什么在每次迭代中都可以为一个指针分配内存而不必先释放它是合法的?

释放动态分配的内存的责任留在了程序员身上。这是合法的,因为尽管有代码检查工具可以标记此问题,但编译器不会强制执行它。

释放动态分配的内存应该以相反的顺序进行。例如:

for (i=0;i<nloc;i++)
    free(sign[i]);

free(sign);

答案 1 :(得分:3)

这是合法的,因为在C语言中,您作为程序员负责内存管理。有一个很好的理由。引用another thread

  

垃圾收集需要用于跟踪分配的数据结构   和/或参考计数。这些会在内存中产生开销,   性能以及语言的复杂性。 C ++被设计为   “接近金属”,换句话说,它具有更高的性能   权衡与便利功能之间的权衡。其他语言使   这种权衡有所不同。这是   选择一种您更喜欢的语言。

不仅要考虑性能和代码大小,而且不同的系统对内存的寻址方式也不同。也正是由于这个原因,考虑到没有垃圾收集可以更改,C易于跨平台移植和维护。

编辑:一些答案提到释放内存空间,而不是指针本身,值得进一步说明。这意味着:free()只是将分配的空间标记为可用,不“释放”或擦除,也没有任何空间其他操作将在该存储空间上发生。这样,程序员仍然有责任删除分配给指针变量的地址。

答案 2 :(得分:2)

  

我的问题是:为什么在每次迭代中为指针分配内存而不必先释放它是合法的?

简短答案

C权衡安全性以获得简单性和性能。

更长的答案

您不会释放指针。您释放指针指向所指向的内存块。

考虑{% for field in form %} {{ field.field.widget.attrs.icon }} {% endfor %} (和malloc)的作用。它们都分配一块内存,如果分配成功,它们将返回一个指向该内存块的指针。分配函数(像所有函数一样)没有洞察力,也没有控制您对返回值所做的任何事情。这些功能甚至都看不到要为其分配返回值的指针。

实施针对它的保护会相当复杂(相对而言,C具有一个非常简单的结构)。首先,请考虑以下代码:

calloc

即使我们做了您所要求的精确操作,此代码也没有内存泄漏。在从第一个malloc释放内存之前,我们重新分配了int * a = malloc(1); int * b = a; a = malloc(1); free(b); free(a); 。效果很好,因为我们已将地址保存在a中。

因此,为了禁止重新分配指向内存块的指针,而没有其他指针指向,运行时环境将需要对此进行跟踪,并且这并非完全无关紧要。而且还需要创建额外的代码来处理所有这些问题。由于此检查需要在运行时进行,因此可能会影响性能。

另外,请记住,即使C在今天看起来可能很低级,但当它出现时它就被认为是高级语言。