C 重复分配内存而不释放内存
下面的代码显示了一个示例,该示例在不首先调用C 重复分配内存而不释放内存,c,pointers,function-pointers,free,dynamic-memory-allocation,C,Pointers,Function Pointers,Free,Dynamic Memory Allocation,下面的代码显示了一个示例,该示例在不首先调用free的情况下重复分配内存。相反,它在循环后释放**符号 #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++)
free
的情况下重复分配内存。相反,它在循环后释放**符号
#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);
}
如果在每个循环结束时释放buffer
,可能会导致p
丢失,因为buffer
和p
共享相同的内存地址
我的问题是:为什么我们可以在每次迭代中为指针分配内存而不必首先释放它是合法的
简短回答
C舍弃安全性以获得简单性和性能
更长的答案
您没有释放指针。释放指针指向的内存块
想想malloc
(和calloc
)做了什么。它们都分配一段内存,如果分配成功,它们将返回指向该内存块的指针。分配函数(与所有函数一样)无法洞察或控制您对返回值的操作。这些函数甚至看不到将返回值赋给的指针
实现对它的保护是相当复杂的(相对来说,C有一个相当简单的结构)。首先,考虑这个代码:
int * a = malloc(1);
int * b = a;
a = malloc(1);
free(b);
free(a);
这段代码没有内存泄漏,即使我们做了您要求的事情。在从第一个malloc调用free之前,我们重新分配了a
。它工作正常,因为我们已将地址保存在b
中
因此,为了不允许重新分配指向没有其他指针指向的内存块的指针,运行时环境需要跟踪这一点,这并不是一件小事。它还需要创建额外的代码来处理所有这些。由于此检查需要在运行时进行,因此可能会影响性能
另外,请记住,尽管C语言在今天看来可能非常低级,但它出现时被认为是高级语言。这是合法的,因为在C语言中,作为程序员,您负责内存管理。这是一个很好的理由。引用
垃圾收集需要数据结构来跟踪分配
和/或参考计数。这些会在内存中产生开销,
性能和语言的复杂性。设计C++
“接近金属”,换句话说,它需要更高的性能
与便利性功能的权衡。其他语言使
这是一种不同的权衡。这是本报告考虑的因素之一
选择一种你喜欢的语言
不仅要考虑性能和代码大小,而且不同的系统对内存有不同的寻址方案。也正是由于这个原因,C很容易跨平台移植和维护,因为没有垃圾收集需要修改
编辑:有些答案提到释放内存空间,而不是指针本身,值得进一步说明这意味着什么:free()只是将分配的空间标记为可用,它不会“释放”或擦除,也不会对该内存空间执行任何其他操作。然后,程序员仍然有义务删除分配给指针变量的地址
为什么我们可以在每次迭代中为指针分配内存而不必首先释放它是合法的
释放动态分配内存的责任留给程序员。这是合法的,因为编译器不强制执行它,尽管有代码检查工具可以标记此问题
释放动态分配的内存应该按照与分配相反的顺序进行。例如:
for (i=0;i<nloc;i++)
free(sign[i]);
free(sign);
for(i=0;我知道sign
和sign[0]、sign[1]等之间的区别吗?它们不是使用了不同的指针吗?代码有内存泄漏(也就是说它调用calloc
的次数比调用free
的次数多)。编译器不会就此发出警告,因为编译器检测此类问题非常困难(如果不是不可能的话)。但是,有一些工具(例如)会在运行时检测内存泄漏。原因之一:有时您希望能够分配更多内存,而不必先释放以前的内存(例如,如果您正在构造一个链表,您不会希望编译器强制您释放列表中的第一个节点,因为您现在已经在列表中创建了第二个节点)调用任何堆分配函数malloc
calloc
realloc
,1)始终选中(!=NULL)确保操作成功的返回值。2)返回的类型为void*
,可分配给任何指针。强制转换只会使代码变得混乱,使其更难理解、调试,我发现了一个异常。请看我的[补充信息]并对此发表一些意见好吗?谢谢,我发现了一个例外。请看我的[补充信息]并对此发表一些意见好吗?谢谢。@coco您不能两次释放相同的分配。我发现了一个例外。请看我的[补充信息]并对此发表一些意见好吗?谢谢。你好,可可。我好像看不到你的留言。如果您需要帮助,欢迎提供更多信息。
for (i=0;i<nloc;i++)
free(sign[i]);
free(sign);