C中的Malloc 2D金字塔数组
Malloc 2D pyramid array in C
我在创建二维数组时遇到问题,其中每个 "row" 都是不同大小的数组,(2*row)+1 个整数以 row=0 开头。
令我烦恼的是,代码适用于一些小输入 (1,2,3),但如果我在打印后尝试释放结构,则在 4 时崩溃,如果我不释放结构,则在 5 时崩溃内存。
typedef struct{
int nrow;
int** numbers;
} pyramid;
pyramid* create_pyramid(int nrow){
//Allocate memory for pyramid
pyramid *p = (pyramid *) malloc (sizeof(pyramid));
if(p == NULL) exit(1);
p->nrow = nrow;
//Allocate memory for numbers
p->numbers = (int**) malloc (sizeof(int*));
if(p->numbers == NULL) exit(1);
//Alocate memory for numbers[i]
int i, nums;
for(i = 0; i < nrow; i++){
nums = (i*2) + 1;
p->numbers[i] = (int*) malloc (nums * sizeof(int));
if(p->numbers[i] == NULL) exit(1);
}
return p;
}
void print_pyramid(pyramid *p){
int i, j, nums, spaces;
for(i = 0; i < p->nrow; i++){
nums = (2*i)+1;
spaces = p->nrow - (i+1);
for(j = 0; j < spaces; j++) printf(" ");
for(j = 0; j < nums; j++){
printf("%d",p->numbers[i][j]);
}
printf("\n");
}
}
void free_pyramid(pyramid *p){
int i;
for(i = 0; i < p->nrow; i++){
free(p->numbers[i]);
}
free(p->numbers);
free(p);
}
int main(int argc, char *argv[]){
if(argc<2) exit(1);
int nrow; sscanf(argv[1], "%d", &nrow);
pyramid *p = create_pyramid(nrow);
print_pyramid(p);
free_pyramid(p);
exit(0);
}
这是我在 运行 使用命令行参数 0-4 的代码时得到的:
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 1
0
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 2
0
000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 3
0
000
00000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 4
0
000
00000
0000000
*** Error in `./a.out': double free or corruption (out): 0x0000000001441050 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fcc5a32d7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7fe0a)[0x7fcc5a335e0a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fcc5a33998c]
./a.out[0x400887]
./a.out[0x40092a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fcc5a2d6830]
./a.out[0x4005e9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 38534 /home/userT/Desktop/pyr/a.out
00600000-00601000 r--p 00000000 08:01 38534 /home/userT/Desktop/pyr/a.out
00601000-00602000 rw-p 00001000 08:01 38534 /home/userT/Desktop/pyr/a.out
01441000-01462000 rw-p 00000000 00:00 0 [heap]
7fcc54000000-7fcc54021000 rw-p 00000000 00:00 0
7fcc54021000-7fcc58000000 ---p 00000000 00:00 0
7fcc5a0a0000-7fcc5a0b6000 r-xp 00000000 08:01 7136 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fcc5a0b6000-7fcc5a2b5000 ---p 00016000 08:01 7136 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fcc5a2b5000-7fcc5a2b6000 rw-p 00015000 08:01 7136 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fcc5a2b6000-7fcc5a475000 r-xp 00000000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a475000-7fcc5a675000 ---p 001bf000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a675000-7fcc5a679000 r--p 001bf000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a679000-7fcc5a67b000 rw-p 001c3000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a67b000-7fcc5a67f000 rw-p 00000000 00:00 0
7fcc5a67f000-7fcc5a6a5000 r-xp 00000000 08:01 7070 /lib/x86_64-linux-gnu/ld-2.23.so
7fcc5a887000-7fcc5a88a000 rw-p 00000000 00:00 0
7fcc5a8a1000-7fcc5a8a4000 rw-p 00000000 00:00 0
7fcc5a8a4000-7fcc5a8a5000 r--p 00025000 08:01 7070 /lib/x86_64-linux-gnu/ld-2.23.so
7fcc5a8a5000-7fcc5a8a6000 rw-p 00026000 08:01 7070 /lib/x86_64-linux-gnu/ld-2.23.so
7fcc5a8a6000-7fcc5a8a7000 rw-p 00000000 00:00 0
7ffc634cc000-7ffc634ed000 rw-p 00000000 00:00 0 [stack]
7ffc635d6000-7ffc635d8000 r--p 00000000 00:00 0 [vvar]
7ffc635d8000-7ffc635da000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
如果我不在 main 的末尾调用 free_pyramid 函数,我会得到这样的结果:
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 1
0
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 2
0
000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 3
0
000
00000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 4
0
000
00000
0000000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 5
39268576
000
00000
0000000
000000000
p->numbers = (int**) malloc (sizeof(int*));
应该是
p->numbers = malloc ( sizeof(int*[nrow]) );
转换为 int**
是多余的,您需要分配一个指针数组而不是一个指针。
就像你在
p->numbers[i] = (int*) malloc (nums * sizeof(int));
您需要为一组变量分配内存,而不仅仅是一个变量。所以这一行:
p->numbers = (int**) malloc (sizeof(int*));
应该是
p->numbers = (int**) malloc (nrow * sizeof(int*));
在这两种情况下 (int*)
和 (int**)
都不需要。
已经解决了如何正确分配内存的机制,但关于您的问题:
让我烦恼的是 代码适用于一些小输入 (1,2,3) 但随后崩溃4 如果我在打印后尝试释放结构,或者在 5 上如果我不释放内存。
即使您还没有拥有它,您的程序在尝试写入内存中尚未正确分配的位置时也可以正常工作。这被称为 undefined behavior (a)。您的程序似乎工作正常,然后突然之间,没有明显的原因,它没有。
稍后,关于释放内存,free
语句仅标记内存位置以允许操作系统在需要时使用它们。它不会立即清除该内存的内容。因此,如果您在释放后尝试访问相同的内存位置,并且操作系统尚未将其用于其他用途,您实际上可能看起来成功地看到了内容。这又是 undefined behavior (b)。
同样,如何分配内存的真正问题已得到解决,但由于金字塔设计中的列与行的数字比率良好、一致,因此可以简化 create_pyramid 函数。 (此示例不使用结构,并用数字 n
填充每一行 n
。)
int ** create_pyramid(int r);
int main(void)
{
int r = 5;
int **p = Create2D(r);
for(int i=0;i<r;i++)
{
for(int j=0;j<(2*i)+1;j++)
{
p[i][j] = i; //populate with numeral representing row.
}
}
return 0;
}
int ** create_pyramid(int r)
{
int **arr;
int c = 2*r-1;
int y = 0;
arr = calloc(c, sizeof(int *));
for(y=0;y<c;y++)
{
arr[y] = calloc((2*y)+1, sizeof(int));
}
return arr;
}
已创建内存的图示:(仅显示前几 行 以节省 space)
我在创建二维数组时遇到问题,其中每个 "row" 都是不同大小的数组,(2*row)+1 个整数以 row=0 开头。
令我烦恼的是,代码适用于一些小输入 (1,2,3),但如果我在打印后尝试释放结构,则在 4 时崩溃,如果我不释放结构,则在 5 时崩溃内存。
typedef struct{
int nrow;
int** numbers;
} pyramid;
pyramid* create_pyramid(int nrow){
//Allocate memory for pyramid
pyramid *p = (pyramid *) malloc (sizeof(pyramid));
if(p == NULL) exit(1);
p->nrow = nrow;
//Allocate memory for numbers
p->numbers = (int**) malloc (sizeof(int*));
if(p->numbers == NULL) exit(1);
//Alocate memory for numbers[i]
int i, nums;
for(i = 0; i < nrow; i++){
nums = (i*2) + 1;
p->numbers[i] = (int*) malloc (nums * sizeof(int));
if(p->numbers[i] == NULL) exit(1);
}
return p;
}
void print_pyramid(pyramid *p){
int i, j, nums, spaces;
for(i = 0; i < p->nrow; i++){
nums = (2*i)+1;
spaces = p->nrow - (i+1);
for(j = 0; j < spaces; j++) printf(" ");
for(j = 0; j < nums; j++){
printf("%d",p->numbers[i][j]);
}
printf("\n");
}
}
void free_pyramid(pyramid *p){
int i;
for(i = 0; i < p->nrow; i++){
free(p->numbers[i]);
}
free(p->numbers);
free(p);
}
int main(int argc, char *argv[]){
if(argc<2) exit(1);
int nrow; sscanf(argv[1], "%d", &nrow);
pyramid *p = create_pyramid(nrow);
print_pyramid(p);
free_pyramid(p);
exit(0);
}
这是我在 运行 使用命令行参数 0-4 的代码时得到的:
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 1
0
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 2
0
000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 3
0
000
00000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 4
0
000
00000
0000000
*** Error in `./a.out': double free or corruption (out): 0x0000000001441050 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fcc5a32d7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7fe0a)[0x7fcc5a335e0a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fcc5a33998c]
./a.out[0x400887]
./a.out[0x40092a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fcc5a2d6830]
./a.out[0x4005e9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 38534 /home/userT/Desktop/pyr/a.out
00600000-00601000 r--p 00000000 08:01 38534 /home/userT/Desktop/pyr/a.out
00601000-00602000 rw-p 00001000 08:01 38534 /home/userT/Desktop/pyr/a.out
01441000-01462000 rw-p 00000000 00:00 0 [heap]
7fcc54000000-7fcc54021000 rw-p 00000000 00:00 0
7fcc54021000-7fcc58000000 ---p 00000000 00:00 0
7fcc5a0a0000-7fcc5a0b6000 r-xp 00000000 08:01 7136 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fcc5a0b6000-7fcc5a2b5000 ---p 00016000 08:01 7136 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fcc5a2b5000-7fcc5a2b6000 rw-p 00015000 08:01 7136 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fcc5a2b6000-7fcc5a475000 r-xp 00000000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a475000-7fcc5a675000 ---p 001bf000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a675000-7fcc5a679000 r--p 001bf000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a679000-7fcc5a67b000 rw-p 001c3000 08:01 7098 /lib/x86_64-linux-gnu/libc-2.23.so
7fcc5a67b000-7fcc5a67f000 rw-p 00000000 00:00 0
7fcc5a67f000-7fcc5a6a5000 r-xp 00000000 08:01 7070 /lib/x86_64-linux-gnu/ld-2.23.so
7fcc5a887000-7fcc5a88a000 rw-p 00000000 00:00 0
7fcc5a8a1000-7fcc5a8a4000 rw-p 00000000 00:00 0
7fcc5a8a4000-7fcc5a8a5000 r--p 00025000 08:01 7070 /lib/x86_64-linux-gnu/ld-2.23.so
7fcc5a8a5000-7fcc5a8a6000 rw-p 00026000 08:01 7070 /lib/x86_64-linux-gnu/ld-2.23.so
7fcc5a8a6000-7fcc5a8a7000 rw-p 00000000 00:00 0
7ffc634cc000-7ffc634ed000 rw-p 00000000 00:00 0 [stack]
7ffc635d6000-7ffc635d8000 r--p 00000000 00:00 0 [vvar]
7ffc635d8000-7ffc635da000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
如果我不在 main 的末尾调用 free_pyramid 函数,我会得到这样的结果:
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 1
0
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 2
0
000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 3
0
000
00000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 4
0
000
00000
0000000
userT@userT-VirtualBox:~/Desktop/pyr$ ./a.out 5
39268576
000
00000
0000000
000000000
p->numbers = (int**) malloc (sizeof(int*));
应该是
p->numbers = malloc ( sizeof(int*[nrow]) );
转换为 int**
是多余的,您需要分配一个指针数组而不是一个指针。
就像你在
p->numbers[i] = (int*) malloc (nums * sizeof(int));
您需要为一组变量分配内存,而不仅仅是一个变量。所以这一行:
p->numbers = (int**) malloc (sizeof(int*));
应该是
p->numbers = (int**) malloc (nrow * sizeof(int*));
在这两种情况下 (int*)
和 (int**)
都不需要。
已经解决了如何正确分配内存的机制,但关于您的问题:
让我烦恼的是 代码适用于一些小输入 (1,2,3) 但随后崩溃4 如果我在打印后尝试释放结构,或者在 5 上如果我不释放内存。
即使您还没有拥有它,您的程序在尝试写入内存中尚未正确分配的位置时也可以正常工作。这被称为 undefined behavior (a)。您的程序似乎工作正常,然后突然之间,没有明显的原因,它没有。
稍后,关于释放内存,free
语句仅标记内存位置以允许操作系统在需要时使用它们。它不会立即清除该内存的内容。因此,如果您在释放后尝试访问相同的内存位置,并且操作系统尚未将其用于其他用途,您实际上可能看起来成功地看到了内容。这又是 undefined behavior (b)。
同样,如何分配内存的真正问题已得到解决,但由于金字塔设计中的列与行的数字比率良好、一致,因此可以简化 create_pyramid 函数。 (此示例不使用结构,并用数字 n
填充每一行 n
。)
int ** create_pyramid(int r);
int main(void)
{
int r = 5;
int **p = Create2D(r);
for(int i=0;i<r;i++)
{
for(int j=0;j<(2*i)+1;j++)
{
p[i][j] = i; //populate with numeral representing row.
}
}
return 0;
}
int ** create_pyramid(int r)
{
int **arr;
int c = 2*r-1;
int y = 0;
arr = calloc(c, sizeof(int *));
for(y=0;y<c;y++)
{
arr[y] = calloc((2*y)+1, sizeof(int));
}
return arr;
}
已创建内存的图示:(仅显示前几 行 以节省 space)