在 c 中释放二维矩阵时正确使用 free()
Correct use of free() when deallocating a 2d matrix in c
我刚开始学习用 c 编写代码,我有几个关于二维矩阵与 free() 命令结合使用的问题。
我知道你首先需要创建一个带指针的数组,指向矩阵的不同列:
double **array = (double **)malloc(5*sizeof(double *));
for(int n = 0; n<5; n++){
array[n] = (double *) malloc(6*sizeof(double));
我知道解除分配此矩阵的正确方法是首先解除分配各个行,然后解除数组指针本身。大致如下:
for (i = 0; i < nX; i++){
free(array[i]); }
free(array);
我的问题是:为什么这是必要的?我知道这是不正确的,但为什么你不能只使用:free(array)?据我了解,这将释放指针数组。当其他东西需要访问它时,列使用的内存不会被覆盖吗? free(array) 会以任何方式导致内存损坏吗?
非常感谢任何帮助!
它不会导致损坏,不会,但会造成内存泄漏。
如果在你的程序中完成一次,它可能并不重要(很多 professional/expensive 应用程序都有 - 小的,无意的 - 内存泄漏),但在循环中重复这个,你可能 运行 一段时间后内存不足。如果您的代码是从外部程序调用的(如果您的代码在库中),情况也是如此。
旁白:不释放缓冲区可能是一种有用的方法(暂时)来检查您在程序中遇到的崩溃是否源于损坏的内存分配或释放(当您无法使用 Valgrind 时)。但最后你想释放一切,一次。
如果你只想执行一个malloc
,你也可以分配一个大块,然后计算行的地址。最后,只需释放大块(此处示例:How do we allocate a 2-D array using One malloc statement)
让我们举个简单的例子:
int **ptr = malloc(2*sizeof *ptr);
int *foo = malloc(sizeof *foo);
int *bar = malloc(sizeof *bar);
ptr[0] = foo;
ptr[1] = bar;
free(ptr);
如果您的建议得到实施,foo
和 bar
现在将成为悬挂指针。如果你只想释放ptr
,你会如何解决这个场景?
您的代码不仅为指针数组(蓝色数组)分配内存,而且在 for 循环中,您还为红色数组分配内存。因此,free(array)
行将仅释放蓝色数组分配的内存,而不是红色数组。你需要释放红色的,就在失去与他们的联系之前;也就是说,在释放蓝色数组之前。
顺便说一句;
Won't the memory that is used by the columns just be overwritten when something else needs acces to it?
没有。操作系统将跟踪您的进程(程序)分配的内存,并且在您的进程终止之前不允许任何其他进程访问分配的内存。在正常情况下——我的意思是,记住 C 语言没有垃圾收集器——OS 永远不知道你已经与分配的内存失去联系 space 并且永远不会尝试 "well, this memory space is not useful for this process anymore; so, let's de-allocate it and serve it for another process."
这是必需的,因为 C 没有垃圾收集器。
一旦您使用 malloc
或类似函数分配内存,只要您的程序是 运行.
,它就会被标记为 "in use"
如果您的程序中不再持有指向该内存的指针,那也没关系。
C语言中没有机制来检查这个并自动释放内存。
此外,当您使用 malloc
分配内存时,该函数不知道您将内存用于什么。对于分配器,它只是字节。
因此,当您 free
一个指针(或指针数组)时,没有逻辑 "realize" 这些是包含内存地址的指针。
这就是 C 语言的简单设计方式:动态内存管理几乎1 完全手动 - 留给程序员,所以你必须调用 free
for每次调用 malloc
.
1 C 语言确实处理了一些在程序中动态分配内存所需的更繁琐的任务,例如查找从何处获得大小为您的空闲连续内存块要求。
我刚开始学习用 c 编写代码,我有几个关于二维矩阵与 free() 命令结合使用的问题。
我知道你首先需要创建一个带指针的数组,指向矩阵的不同列:
double **array = (double **)malloc(5*sizeof(double *));
for(int n = 0; n<5; n++){
array[n] = (double *) malloc(6*sizeof(double));
我知道解除分配此矩阵的正确方法是首先解除分配各个行,然后解除数组指针本身。大致如下:
for (i = 0; i < nX; i++){
free(array[i]); }
free(array);
我的问题是:为什么这是必要的?我知道这是不正确的,但为什么你不能只使用:free(array)?据我了解,这将释放指针数组。当其他东西需要访问它时,列使用的内存不会被覆盖吗? free(array) 会以任何方式导致内存损坏吗?
非常感谢任何帮助!
它不会导致损坏,不会,但会造成内存泄漏。
如果在你的程序中完成一次,它可能并不重要(很多 professional/expensive 应用程序都有 - 小的,无意的 - 内存泄漏),但在循环中重复这个,你可能 运行 一段时间后内存不足。如果您的代码是从外部程序调用的(如果您的代码在库中),情况也是如此。
旁白:不释放缓冲区可能是一种有用的方法(暂时)来检查您在程序中遇到的崩溃是否源于损坏的内存分配或释放(当您无法使用 Valgrind 时)。但最后你想释放一切,一次。
如果你只想执行一个malloc
,你也可以分配一个大块,然后计算行的地址。最后,只需释放大块(此处示例:How do we allocate a 2-D array using One malloc statement)
让我们举个简单的例子:
int **ptr = malloc(2*sizeof *ptr);
int *foo = malloc(sizeof *foo);
int *bar = malloc(sizeof *bar);
ptr[0] = foo;
ptr[1] = bar;
free(ptr);
如果您的建议得到实施,foo
和 bar
现在将成为悬挂指针。如果你只想释放ptr
,你会如何解决这个场景?
您的代码不仅为指针数组(蓝色数组)分配内存,而且在 for 循环中,您还为红色数组分配内存。因此,free(array)
行将仅释放蓝色数组分配的内存,而不是红色数组。你需要释放红色的,就在失去与他们的联系之前;也就是说,在释放蓝色数组之前。
顺便说一句;
Won't the memory that is used by the columns just be overwritten when something else needs acces to it?
没有。操作系统将跟踪您的进程(程序)分配的内存,并且在您的进程终止之前不允许任何其他进程访问分配的内存。在正常情况下——我的意思是,记住 C 语言没有垃圾收集器——OS 永远不知道你已经与分配的内存失去联系 space 并且永远不会尝试 "well, this memory space is not useful for this process anymore; so, let's de-allocate it and serve it for another process."
这是必需的,因为 C 没有垃圾收集器。
一旦您使用 malloc
或类似函数分配内存,只要您的程序是 运行.
如果您的程序中不再持有指向该内存的指针,那也没关系。 C语言中没有机制来检查这个并自动释放内存。
此外,当您使用 malloc
分配内存时,该函数不知道您将内存用于什么。对于分配器,它只是字节。
因此,当您 free
一个指针(或指针数组)时,没有逻辑 "realize" 这些是包含内存地址的指针。
这就是 C 语言的简单设计方式:动态内存管理几乎1 完全手动 - 留给程序员,所以你必须调用 free
for每次调用 malloc
.
1 C 语言确实处理了一些在程序中动态分配内存所需的更繁琐的任务,例如查找从何处获得大小为您的空闲连续内存块要求。