【问题标题】:C allocating dynamic memory in a function - same resultsC在函数中分配动态内存 - 结果相同
【发布时间】:2013-12-20 12:44:58
【问题描述】:

我尝试创建一个多维数组并编写了一个函数,但是当我检查我的矩阵时,我意识到我的指针的值是相同的,但它们的地址是不同的。为什么:)

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

int **matrix(int a,int b){
    int i;
    int **x;
    x = (int**)malloc(a * sizeof(int*));
    for (i = 0; i < a; i++) {
        x[i] = (int*)malloc(b * sizeof(int));
    }
    return x;
}

int main()
{
    int **m1, **m2;
    m1=matrix(3,3);
    m2=matrix(3,3);
    printf("Values: %d %d\n",m1[1][1],m2[1][1]);
    printf("Addresses: %d %d",&m1[1][1],&m2[1][1]);
    return 0;
}

【问题讨论】:

  • 您的值未初始化,因此它们可以是任何值。地址应该是不同的,为什么你期望相同?
  • 在分配 m1 后,它得到一个地址。然后当 m2 被分配时,它被分配到不同的地址,因为 m1 仍然存在并且还没有被释放(动态分配)。
  • 因为我得到了相同的结果。我使用代码块,我的屏幕输出是值:3870600 3870600 地址:3870684 3770780
  • 对不起我的英语.s

标签: c function pointers memory dynamic


【解决方案1】:

在 m1[1][1] 的情况下,您将打印数组中的值。它们不是指针值。由于您尚未将它们初始化为任何值,因此它们可以是任何值。在您的情况下,它们变得相同
&m1[1][1] 虽然是一个指针。由于您分配了两次内存,因此它们具有不同的值。 (数组地址不同)

【讨论】:

  • 您可能会考虑编辑您的答案,因为您的答案并不完全说明用户在问什么!
【解决方案2】:

内存泄漏迫在眉睫!
首先,这里有一个可能的内存泄漏程序。您正在为 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,那么你将碰巧获得零初始化内存,但你不能确定这将永远是这样......你应该问的问题不是为什么,而是为什么不什么是赔率

【讨论】:

  • 其实我想问为什么值是一样的,但我猜问错了,因为我已经知道地址必须不同
  • @BerkSahin:巧合,将其添加到我的答案中
  • @BerkSahin:我做了更多的挖掘工作,并查看了您的代码。检查我在答案中链接到的键盘,它修复了您的代码的几个问题,并阅读我的其余编辑,因为将来可能会有更新
猜你喜欢
  • 2012-12-26
  • 2021-10-15
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
相关资源
最近更新 更多