动态内存分配问题(以C为单位)

时间:2011-06-13 12:26:39

标签: c memory-management malloc dynamic-memory-allocation

请考虑以下代码:

#include <stdio.h>
#include <malloc.h>

void allocateMatrix(int **m, int l, int c)
{
    int i;

    m = (int**) malloc( sizeof(int*) * l );
    for(i = 0; i < l; i++)
        m[i] = (int*) malloc( sizeof(int) * c );
}

int main()
{
    int **m;
    int l = 10, c = 10;
    allocateMatrix(m, l, c);
    m[0][0] = 9;
    printf("%d", m[0][0]);

    return 0;
}

上面的代码会产生内存分配错误并会崩溃。

但是下面的代码会正常运行,问题是:为什么?

#include <stdio.h>
#include <malloc.h>

int** allocateMatrix(int l, int c)
{
    int i;

    int **m = (int**) malloc( sizeof(int*) * l );
    for(i = 0; i < l; i++)
        m[i] = (int*) malloc( sizeof(int) * c );
    return m;
}

int main()
{
    int **m;
    int l = 10, c = 10;
    m = allocateMatrix(l, c);
    m[0][0] = 9;
    printf("%d", m[0][0]);

    return 0;
}

我无法理解为什么第一个代码崩溃,因为我只是将指针指针m(保存矩阵的内存第一个内存地址的变量)作为参数传递。我发现代码之间没有区别(实际上)。我将不胜感激。

谢谢你, Rafael Andreatta

4 个答案:

答案 0 :(得分:7)

在第一个示例中,您不初始化m。你只需要更改它的副本。所以,换句话说,来电者永远不会看到你对m做了什么。

在第二个示例中,您分配内存,然后返回指向它的指针。这是有效的。

你可能能够像这样修复你的第一个例子(未经测试但应该有效):

void allocateMatrix(int ***m, int l, int c)
{
    int i;

    *m = malloc( sizeof(int*) * l );
    for(i = 0; i < l; i++)
        (*m)[i] = malloc( sizeof(int) * c );
}


/* ... */

allocateMatrix(&m, l, c);

修改

我花了一段时间才找到它。像往常一样,C FAQ对此有所说明。

答案 1 :(得分:1)

函数allocateMatrix接收传递的变量m的副本,而不是您从main传递的变量。因此,在第一个示例中,m未初始化,当您尝试访问时,您会遇到分段错误。

答案 2 :(得分:1)

这是一个棘手的问题,因为:

void allocateMatrix(int **m, int l, int c);

你是间接的一个层面。如果传递指针,则指向的值实际上是通过引用传递的。但是,实际指针值被复制到堆栈上,即仍然按值传递。因此,您的分配函数具有堆地址的本地副本,但在前面的范围中永远不会将其重新分配给m

要解决此问题,您可以使用第二种情况,或者使用:

void allocateMatrix(int ***m, int l, int c)
{
    int i;
    *m = (int**) malloc( sizeof(int*) * l );
    for(i = 0; i < l; i++)
        (*m)[i] = (int*) malloc( sizeof(int) * c );
}

并传递&m

我还想在C中指出,你可能最好不要使用malloc的结果,尽管你需要使用C ++。请参阅this answer

答案 3 :(得分:0)

因为在第一个例子中变量m(在main中)没有改变。要更改它,必须将其作为引用(在C ++中)或通过指针(在纯C中)传递。