内存泄漏迫在眉睫!
首先,这里有一个可能的内存泄漏程序。您正在为 2 个 矩阵 分配内存,但对您free 分配的内存毫无意义。你应该。在堆上分配的所有内存都是您的责任,您的工作是在您完成后确保该内存为free'ed。可能实现如下功能:
void free_matrix(int **matrix, int len)
{
if (matrix == NULL) return;//don't try and free NULL pointers
while(len--) free(matrix[len]);
free(matrix);
}
在您打印出需要打印的内容后在您的主函数中调用:
free_matrix(m1, 3);
m1 = NULL;//setting unused pointers to NULL is a good habit
free_matrix(m1,3);//won't cause problems
free_matrix(m2, 3);
free_matrix(m2, 1);//ERROR!
您也无法检查malloc 调用是否真的成功。如果没有足够的可用内存,malloc 返回 null,您应该处理这个问题。至少做到:
some_ptr = malloc(sizeof(*some_ptr));
if (some_ptr == NULL) exit(EXIT_FAILURE);//macro expands to 1
无论如何,我已经写了this codepad,它试图一遍又一遍地释放和重新分配相同的矩阵,直到内存中的值不同。事实证明,至少在键盘上,它们总是相同的。
我目前正在浏览 linux 内核代码和网络,看看是否有这个原因。也许当内核空闲时 Linux 会擦除堆内存,或者它可能是一个键盘的东西......无论哪种方式,请继续关注更新:)
基本上,malloc 不会初始化它分配的内存。操作系统对空闲内存的处理取决于操作系统。我已经在我的 64 位 linux 系统上尝试了下面的代码,它使用编译得很好
gcc -std=c99 -Wall src.c -o temp
它表明矩阵确实包含不同的值,但在我的情况下主要是0。无论如何,这是代码:
#include <stdio.h>
#include <stdlib.h>
void **matrix(int a,int b)
{
int i;
unsigned int **x;
x = malloc(a * sizeof(*x));
if (x == NULL) exit(EXIT_FAILURE);
for (i = 0; i < a; i++)
{
x[i] = malloc(b * sizeof(*(x[i])));
if (x[i] == NULL) exit(EXIT_FAILURE);
}
return (void **)x;
}
void free_matrix(void ***m, int l)
{
if (*m == NULL) return;
while(l--) free((*m)[l]);
free(*m);
*m = NULL;
}
int main( void )
{
unsigned int **m1, **m2, c=0;
m1 = (unsigned int **) matrix(3,3);
m2 = (unsigned int **) matrix(3,3);
printf("%lu <> %lu\n", sizeof(m1[1][1]), sizeof(m1));//4 <> 4 -> 32 bit, 4 <> 8 -> 64
while(*(m1[1]+1) == *(m2[1]+1) && c < 101)
{
++c;
free_matrix((void ***) &m1,3);
m1 = (unsigned int **) matrix(3,3);
}
if (c == 101)
{
for(c=0;c<3;++c) printf("%u %u %u\n%u %u %u\n\n",*(m1[c]), *(m1[c]+1), *(m1[c]+2),*(m2[c]), *(m2[c]+1), *(m2[c]+2));
}
else
{
printf("Different vals after %d tries\n", c);
}
printf("Values: %u %u %c\n",m1[1][1],m2[1][1], (unsigned char) m1[1][1]);
printf("Addresses: %p %p\n",(void *) (m1[1]+1), (void *) (m2[1]+1));
free_matrix((void ***)&m1, 3);
free_matrix((void ***)&m2,3);
return 0;
}
我得到的输出示例如下:
4 8
12546112 0 0
0 0 0
12546144 0 0
0 0 0
0 0 0
0 0 0
值:0 0
地址:0xbf7054 0xbf70d4
无论如何,我希望这一点,我的其余回答可以为您解决一两件事。
要获得实际的地址,您必须编写:
printf("Addresses: %p, %p\n", (void *) &m1[1][1], (void *)&m1);
相对于:
printf("Addresses: %d %d",&m1[1][1],&m2[1][1]);
因为m1[1][1] 不是指针! m1 是一个指向 int 的指针,所以 m[1] 是一个指向 int 的指针,而 m1[1][1] 是一个 int,而不是一个指针。
哦,还没有完成malloc 的返回值的转换。它隐藏了可能的错误,malloc 将返回兼容的指针类型或NULL。
但是为什么他们的地址不一样呢?很简单:您正在分配 2 个单独的堆内存块。您不会两次分配相同的内存(这是不可能的)。
您正在尝试打印存储在堆中 2 个不同位置的那些值的地址。
这就像建造两座在各方面完全相同的房子,只是你在不同的城市建造它们。他们的地址将是唯一的。
值相同的事实是巧合。 malloc 不会改变内存的内容,所以如果内存块自上次使用以来恰好设置为0,那么你将碰巧获得零初始化内存,但你不能确定这将永远是这样......你应该问的问题不是为什么,而是为什么不或什么是赔率