【问题标题】:2D Dynamic Array Allocation and Passing by Reference in CC 中的 2D 动态数组分配和通过引用传递
【发布时间】:2012-04-20 13:16:22
【问题描述】:

请比我聪明的人向我解释为什么以下代码段错误?通过引用分配内存没有问题,但是一旦我尝试通过引用分配任何内容或释放,就会发生段错误。

我确定我错过了一些关于指针和通过引用传递的基本概念,希望能有所启发。

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

void allocateMatrix(float ***);
void fillMatrix(float ***);
void freeMatrix(float **);

int main() {
    float **matrix;

    allocateMatrix(&matrix);        // this function calls and returns OK
    fillMatrix(&matrix);            // this function will segfault
    freeMatrix(matrix);             // this function will segfault

    exit(0);
}

void allocateMatrix(float ***m) {
    int i;
    m = malloc(2*sizeof(float*));
    for (i = 0; i < 2; i++) {
        m[i] = malloc(2*sizeof(float));
    }
    return;
}

void fillMatrix(float ***m) {
    int i,j;
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            (*m)[i][j] = 1.0;        // SEGFAULT
        }
    }
    return;
}

void freeMatrix(float **m) {
    int i; 
    for (i = 0; i < 2; i++) {
        free(m[i]);                  // SEGFAULT
    }
    free(m);
    return;
}

【问题讨论】:

  • 编译我其实有点惊讶。 “void allocateMatrix(&m)”可能没有按预期将 m 键入为 float**。此外,C 中的引用方式与 C++ 中的引用方式不同。
  • 为什么freeMatrix 等的签名在声明和定义时会有所不同?
  • keety,Corbin:抱歉复制粘贴失败,已修复
  • 只是为了强调一点,您在这里所做的(并已被乔纳森的回答纠正)是 不是 2D 数组,而是 2D 数组的仿真。 C 语言中直接内置了多维数组,这些数组更易于使用,尤其是分配。看看您似乎对 C 的体验状态,最好先学习和使用该功能,然后再进行复杂的迭代分配。
  • 我理解 Jens 你为什么会提出这样的建议,你是对的:在你跑步之前总是更容易走路。我假设您所说的内置多维数组是静态的编译时float matrix[2][2];。这一切都很好,但我现在需要了解动态的、传递引用。

标签: c multidimensional-array segmentation-fault pass-by-reference dynamic-memory-allocation


【解决方案1】:

这里有一组问题:

void allocateMatrix(float ***m) {
    int i;
    m = malloc(2*sizeof(float*));
    for (i = 0; i < 2; i++) {
        m[i] = malloc(2*sizeof(float));
    }
    return;
}

您需要分配给*m 以将信息返回给调用代码,并且您还需要在循环中分配给(*m)[i]

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

至少有可能其他功能都可以。 fillMatrix() 被正确写入和调用,尽管可以通过丢失指针中的第三个 * 来简化它:

void fillMatrix(float **m)
{
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
            m[i][j] = 1.0;        
    }
}

建议将三重指针传递给freeMatrix(),这样您就可以在调用函数中将指针归零:

void freeMatrix(float ***m)
{
    for (int i = 0; i < 2; i++)
        free((*m)[i]);
    free(*m);
    *m = 0;
}

调用然后变成:

allocateMatrix(&matrix);
fillMatrix(matrix);
freeMatrix(&matrix);   

【讨论】:

  • 谢谢乔纳森,这很有意义。
【解决方案2】:

善用间接。尽量与格式保持一致。它提高了可读性并减少了错误。例如

函数调用:

    allocateMatrix  &matrix
    fillMatrix  &matrix
    freeMatrix  &matrix

声明

void allocateMatrix  float ***m
void fillMatrix  float ***m
void freeMatrix  float ***m

处理

    (*m)[i] = malloc(2 * sizeof(float))
    (*m)[i][j] = 1.0
    free  (*m)[i]

【讨论】:

  • 这个有道理,我现在就尝试实现。
【解决方案3】:

从函数返回指针可能是分配内存的更好方法:

float **allocateMatrix() {
    int i;
    float **m;

    m = malloc(2*sizeof(float *));
    for (i = 0; i < 2; i++) {
        m[i] = malloc(2*sizeof(float));
    }

    return m;
}

int main() {
    float **m;

    m = allocateMatrix();

    /* do other things 
       fillMatrix(matrix);
       freeMatrix(&matrix);
    */
}

【讨论】:

    猜你喜欢
    • 2010-10-06
    • 2014-05-26
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 2011-05-08
    • 2012-11-23
    • 1970-01-01
    • 2020-10-18
    相关资源
    最近更新 更多