将2D数组转换为动态数组会导致核心转储

时间:2015-04-08 06:28:56

标签: c arrays malloc

我有一个完美的代码,使用C语言的浮点变量vxy的2D数组。行(rrow)的大小是在代码内计算的 - 列(ccol)大小已知。所以我尝试在此论坛中使用代码片段进行转换,这两者都会导致分段错误这两个代码是i)来自how to allocate memory dynamically for a two dimensional array的Bryan方法和ii)使用指针来自http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/的指针方法。我选择了这些方法,因为代码已经可以使用2D数组,因此其余代码将在此更改后继续存在。

static float vxy[5000][ccol] ;
vxy[r][c] = ... 

原始2D声明和用法如上:

#include <stdlib.h>

int main(void)
{
        int num_row = 3, num_col = 2, r;
        int ** A;

        A = malloc(num_row*(sizeof(*A)+num_col*sizeof(**A)));

        for (r = 0; r < num_row; r++)
        {
                A[r] = (int*)(A+num_row)+r*num_col;
        }

        /* Accessing element at row r and column c is through:
         *
         *      A[r][c].
         */

        free(A);

        return 0;
}

基于以上所述的实现是:

int r;
float ** vxy;

    vxy = malloc(rrow*(sizeof(*vxy)+ ccol*sizeof(**vxy)));

    for (r = 0; r < rrow; r++)  {
        vxy[r] = (float*)(vxy + rrow) + r*ccol;
    }

第二种方法是:

        float **vxy = (float **)malloc(rrow * sizeof(float *));
        for (i=0; i<rrow; i++)
             vxy[i] = (float *)malloc(ccol * sizeof(float));

我用以下内容更新了上面的第二种方法 - 我在vxy [i] = malloc(ccol * sizeof(float))的行上得到了“程序接收信号SIGSEGV,Segmentation fault”;

    float **vxy = malloc(rrow * sizeof(float *));
    if (vxy = NULL) {
          printf ("Memory allocation error.\n");
//        return NULL;
    }

    for (i = 0; i < rrow; i++)
        vxy[i] = malloc(ccol * sizeof(float)); 

我的实施似乎出了什么问题? 更新:我更新了方法一的源代码的完整代码。我还想知道如何释放分配并解决失败的malloc情况。

2 个答案:

答案 0 :(得分:2)

我很抱歉你的2D分配有困难,这真的不太难。要使用array[x][y]表示法动态分配和访问元素,需要将x指针分配给float的数组(您的行),然后分配y数组每行的float(您的元素/列)。 (与分配字符串指针数组以保存文本行没什么不同)

显示没有错误检查分配的callocm行和n列)的简单分配/初始化函数的示例是:< / p>

float **mtrx_calloc (size_t m, size_t n)
{
    register size_t i;
    float **array = calloc (m, sizeof *array);

    for (i = 0; i < m; i++)
    {
        array [i] = calloc (n, sizeof **array);
    }
    return array;
}

要分配3x4矩阵,您可以像这样使用它:

float **matrix = mtrx_calloc (3, 4);

然后,您可以使用matrix[x][y]表示法访问所有元素,从而操纵矩阵。另请注意使用size_t代替int。您的rowscolumns以及iterator永远不会消极,因此选择size_tunsigned类型更有意义。

有时候不是查看代码片段,而是有一个有效的例子。我汇总了一个简短的工作示例来帮助您,包括我们在评论及以上所讨论的所有要点。它包括上面省略的内存分配错误检查。如果您有任何疑问,请发表评论。

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

float **mtrx_calloc (size_t m, size_t n);             /* initialize elements to 0  */
void mtrx_prn (size_t m, size_t n, float **matrix);   /* print matrix with/pad     */
void mtrx_free (size_t m, float **matrix);            /* free memory allocated     */

int main (void)
{
    /* allocate the 3x4 matrix */
    float **matrix = mtrx_calloc (3, 4);

    /* fill with misc values */
    register size_t i = 0, j = 0;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 4; j++)
            matrix [i][j] = (float)(i + j);
    }

    /* print matrix */
    printf ("\nThe dynamically allocated 3x4 matrix is:\n\n");
    mtrx_prn (3, 4, matrix);

    /* free memory alocated */
    mtrx_free (3, matrix);

    /* just to make it look pretty */
    printf ("\n");

    return 0;
}

/* allocate/initialize mxn matrix */
float **mtrx_calloc (size_t m, size_t n)
{
    register size_t i;
    float **array = calloc (m, sizeof *array);

    if (!array) {   /* validate allocation  */
        fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
        exit (EXIT_FAILURE);
    }

    for (i = 0; i < m; i++)
    {
        array[i] = calloc (n, sizeof **array);

        if (!array[i]) {   /* validate allocation  */
            fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
            exit (EXIT_FAILURE);
        }
    }
    return array;
}

/* print a (m x n) matrix (check pad alloc) */
void mtrx_prn (size_t m, size_t n, float **matrix)
{
    register size_t i, j;

    for (i = 0; i < m; i++)
    {
        char *pad = "[ ";
        for (j = 0; j < n; j++)
        {
            printf ("%s%6.3f", pad, matrix [i][j]);
            pad = ", ";
        }
        printf ("%s", " ]\n");
    }
}

void mtrx_free (size_t m, float **matrix)
{
    register size_t i;

    for (i = 0; i < m; i++)
    {
        free (matrix [i]);
    }
    free (matrix);
}

<强>输出

(注意:填充misc值等式已更改,以防止在输入大m x n时出现溢出,因此输出值将与下面不同)

$ ./bin/mtrx_dyn_example

The dynamically allocated 3x4 matrix is:

[  1.900,  2.800,  3.700,  4.600 ]
[  2.800,  3.700,  4.600,  5.500 ]
[  3.700,  4.600,  5.500,  6.400 ]

使用valgrind进行泄漏检查

当您动态创建/分配内存块时,负责跟踪您已分配的内容,并保留起始地址内存块,当你不再需要时,释放内存块。帮助您检查内存使用情况的好工具是内存检查程序,例如valgrind。 (类似的工具适用于所有平台)。简单易用,只需valgrind ./progname。它将确认您是否仍然不同意任何块以及是否存在关于已分配块的访问错误:

$ valgrind ./bin/mtrx_dyn_example
==15800== Memcheck, a memory error detector
==15800== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==15800== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==15800== Command: ./bin/mtrx_dyn_example
==15800==

The dynamically allocated 3x4 matrix is:

[  1.900,  2.800,  3.700,  4.600 ]
[  2.800,  3.700,  4.600,  5.500 ]
[  3.700,  4.600,  5.500,  6.400 ]

==15800==
==15800== HEAP SUMMARY:
==15800==     in use at exit: 0 bytes in 0 blocks
==15800==   total heap usage: 4 allocs, 4 frees, 72 bytes allocated
==15800==
==15800== All heap blocks were freed -- no leaks are possible
==15800==
==15800== For counts of detected and suppressed errors, rerun with: -v
==15800== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

答案 1 :(得分:0)

问题在于指向浮点数和实际浮点数之间的相互作用,如引用的答案中所提到的,尝试删除类型转换,看看你得到了什么。

两种方法都有效(但以不同的方式访问),还有一个 first 方法,它创建一个1-d数组,其中代表一个二维数组(因此被访问)如a[i+j*r]),而(第一和第二)方法实际上分配一个二维数组(作为a[i][j]访问)。

尝试使用calloc如果这有帮助,尽管malloc应该没问题

当使用任一方法确保您不会访问已分配数组中的内存越界时,也尝试正确修复索引(在循环中)