将二维数组转换为动态数组会导致核心转储
Converting a 2D array into a dynamic array causes core dump
我有一个用 C 语言编写的带有浮点变量 vxy 的二维数组的完美工作代码。行 (rrow) 的大小正在代码内部计算 - 列 (ccol) 的大小已知。所以我尝试在这个论坛中使用代码片段进行转换,但都导致了分段错误。这两个代码是 i) how to allocate memory dynamically for a two dimensional array and ii) Using pointer to a pointer method from http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ 中的 Bryan 方法。我之所以选择这些方法,是因为代码已经适用于二维数组,因此其余代码将在这次更改中幸存下来。
static float vxy[5000][ccol] ;
vxy[r][c] = ...
原二维声明及用法如上:
#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));
行得到了 "Program received signal 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 失败的情况。
问题在于指向浮点数的指针和实际浮点数之间的相互作用,如参考答案中所述,请尝试删除类型转换并查看结果。
两种方法都有效(但访问方式不同),还有一个 first 方法创建一个一维数组,代表一个二维数组(因此访问为 a[i+j*r]
),而(第一个和)第二个方法实际上分配了一个二维数组(访问为 a[i][j]
)。
如果有帮助,也尝试使用 calloc,尽管 malloc 应该没问题
同时尝试在使用任何一种方法时正确修复索引(在循环中)以确保您不会越界访问分配数组中的内存
很抱歉您在 2D 分配上遇到困难,这真的不是太难。要使用 array[x][y]
符号动态分配和访问元素,您需要分配 x
指向 float
数组(您的行)的指针,然后分配 y
数组每行 float
(您的 elements/columns)。 (与分配一个指向字符串的指针数组来保存文本行没有什么不同)
一个简单的 allocation/initialization 函数示例 calloc
(有 m
行和 n
列)显示 没有 分配错误检查是:
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
。您的 rows
和 columns
以及 iterator
永远不会是负数,因此选择 size_t
或 unsigned
类型更有意义。
有时,与其查看代码片段,不如有一个可运行的示例。我整理了一个简短的工作示例来帮助您,其中包括我们迄今为止在评论和上面讨论的所有要点。它包括上面省略的内存分配错误检查。如果您有任何问题,请发表评论。
#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);
}
输出
(注意:填充杂项值等式已更改,以防止输入大 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 进行泄漏检查
当你是creating/allocating动态内存块时,你负责跟踪你分配的内容,保存内存块的起始地址,当你不再需要它时释放内存块。帮助您检查内存使用情况的一个很好的工具是内存检查器,例如 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)
我有一个用 C 语言编写的带有浮点变量 vxy 的二维数组的完美工作代码。行 (rrow) 的大小正在代码内部计算 - 列 (ccol) 的大小已知。所以我尝试在这个论坛中使用代码片段进行转换,但都导致了分段错误。这两个代码是 i) how to allocate memory dynamically for a two dimensional array and ii) Using pointer to a pointer method from http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ 中的 Bryan 方法。我之所以选择这些方法,是因为代码已经适用于二维数组,因此其余代码将在这次更改中幸存下来。
static float vxy[5000][ccol] ;
vxy[r][c] = ...
原二维声明及用法如上:
#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));
行得到了 "Program received signal 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 失败的情况。
问题在于指向浮点数的指针和实际浮点数之间的相互作用,如参考答案中所述,请尝试删除类型转换并查看结果。
两种方法都有效(但访问方式不同),还有一个 first 方法创建一个一维数组,代表一个二维数组(因此访问为 a[i+j*r]
),而(第一个和)第二个方法实际上分配了一个二维数组(访问为 a[i][j]
)。
如果有帮助,也尝试使用 calloc,尽管 malloc 应该没问题
同时尝试在使用任何一种方法时正确修复索引(在循环中)以确保您不会越界访问分配数组中的内存
很抱歉您在 2D 分配上遇到困难,这真的不是太难。要使用 array[x][y]
符号动态分配和访问元素,您需要分配 x
指向 float
数组(您的行)的指针,然后分配 y
数组每行 float
(您的 elements/columns)。 (与分配一个指向字符串的指针数组来保存文本行没有什么不同)
一个简单的 allocation/initialization 函数示例 calloc
(有 m
行和 n
列)显示 没有 分配错误检查是:
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
。您的 rows
和 columns
以及 iterator
永远不会是负数,因此选择 size_t
或 unsigned
类型更有意义。
有时,与其查看代码片段,不如有一个可运行的示例。我整理了一个简短的工作示例来帮助您,其中包括我们迄今为止在评论和上面讨论的所有要点。它包括上面省略的内存分配错误检查。如果您有任何问题,请发表评论。
#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);
}
输出
(注意:填充杂项值等式已更改,以防止输入大 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 进行泄漏检查
当你是creating/allocating动态内存块时,你负责跟踪你分配的内容,保存内存块的起始地址,当你不再需要它时释放内存块。帮助您检查内存使用情况的一个很好的工具是内存检查器,例如 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)