我int ***a在C中有一个指针变量.我将它作为&aie引用传递给函数.在函数中我得到一个类型的指针变量int ****a.我正在分配这样的内存.
*a=(int***)malloc(no1*sizeof(int**));
some loop from 0 to no1
(*a)[++l]=(int**)malloc((no1+1)*sizeof(int*));
some loop from 0 to no1
(*a)[l][h]=(int*)malloc(2*sizeof(int));
Run Code Online (Sandbox Code Playgroud)
这只是我分配内存的时间.没有给出实际的程序; 这里没有错误.但是当我要这样做时:
(*a)[l][h][0]=no1;
Run Code Online (Sandbox Code Playgroud)
它给了我一个"分段错误"错误,我无法理解为什么.
更新: 我写了一个示例程序,它只分配内存.这也给出了"分段错误"错误.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
void allocate(int ****a)
{
int i,j,k;
if(((*a)=(int***)malloc(5*sizeof(int**)))==NULL)
{
printf("\nError in allocation of double pointer array\n");
exit(0);
}
for(i=0;i<5;i++)if(((*a)[i]=(int**)malloc(4*sizeof(int*)))==NULL)
{
printf("\nError in allocation of single pointer array on index [%d]\n",i);
exit(0);
}
for(i=0;i<5;i++)
for(j=0;j<4;i++)
if(((*a)[i][j]=(int*)malloc(3*sizeof(int)))==NULL)
{
printf("\nError in allocation of array on index [%d][%d]\n",i,j);
exit(0);
}
for(i=0;i<5;i++)
for(j=0;j<4;i++)
for(k=0;k<3;k++)
(*a)[i][j][k]=k;
}
main()
{
int ***a;
int i,j,k;
allocate(&a);
for(i=0;i<5;i++)
for(j=0;j<4;i++)
for(k=0;k<3;k++)
printf("\na[%d][%d][%d] = %d ",i,j,k,a[i][j][k]);
}
Run Code Online (Sandbox Code Playgroud)
你的代码有:
for(i=0;i<5;i++)
for(j=0;j<4;i++)
Run Code Online (Sandbox Code Playgroud)
几次.第二个循环应该是递增j,而不是i.copy'n'paste要非常小心.
此代码不会崩溃(但会泄漏).
#include <stdio.h>
#include <stdlib.h>
void allocate(int ****a);
void allocate(int ****a)
{
int i,j,k;
printf("allocate: 1B\n");
if(((*a)=(int***)malloc(5*sizeof(int**)))==NULL)
{
printf("\nError in allocation of double pointer array\n");
exit(0);
}
printf("allocate: 1A\n");
printf("allocate: 2B\n");
for(i=0;i<5;i++)
if(((*a)[i]=(int**)malloc(4*sizeof(int*)))==NULL)
{
printf("\nError in allocation of single pointer array on index [%d]\n",i);
exit(0);
}
printf("allocate: 2A\n");
printf("allocate: 3B\n");
for(i=0;i<5;i++)
for(j=0;j<4;j++)
if(((*a)[i][j]=(int*)malloc(3*sizeof(int)))==NULL)
{
printf("\nError in allocation of array on index [%d][%d]\n",i,j);
exit(0);
}
printf("allocate: 3A\n");
printf("allocate: 4B\n");
for(i=0;i<5;i++)
for(j=0;j<4;j++)
for(k=0;k<3;k++)
(*a)[i][j][k]=k;
printf("allocate: 4A\n");
}
int main(void)
{
int ***a;
int i,j,k;
allocate(&a);
for(i=0;i<5;i++)
for(j=0;j<4;j++)
for(k=0;k<3;k++)
printf("a[%d][%d][%d] = %d\n",i,j,k,a[i][j][k]);
}
Run Code Online (Sandbox Code Playgroud)
由于您没有向我们展示大部分代码,因此很难预测您是如何处理错误的,但同样地,由于您正在获取核心转储,因此您必须处理不当内容.
这里有一些工作代码 - 没有检查,valgrind因为它不适用于Mac OS X 10.8 - 似乎工作.分配失败的错误恢复未完成,并且还缺少销毁完全分配的数组的功能.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int ***allocate_3d_array(int no1, int ****a)
{
*a = (int***)malloc(no1 * sizeof(int**));
if (*a == 0)
return 0;
for (int l = 0; l < no1; l++)
{
if (((*a)[l]=(int**)malloc((no1+1)*sizeof(int*))) == 0)
{
while (l > 0)
free((*a)[--l]);
return 0;
}
}
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
if (((*a)[l][h]=(int*)malloc(2*sizeof(int))) == 0)
{
/* Leak! */
return 0;
}
}
}
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
(*a)[l][h][k] = 10000 * l + 100 * h + k;
return *a;
}
int main(void)
{
int no1 = 5;
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
printf("a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
// free memory - added by harpun; reformatted by Jonathan Leffler
// Would be a function normally — see version 2 code.
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
free(a[l][h]);
free(a[l]);
}
free(a);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
a[0][0][0] = 000000 a[0][0][1] = 000001
a[0][1][0] = 000100 a[0][1][1] = 000101
a[0][2][0] = 000200 a[0][2][1] = 000201
a[0][3][0] = 000300 a[0][3][1] = 000301
a[0][4][0] = 000400 a[0][4][1] = 000401
a[1][0][0] = 010000 a[1][0][1] = 010001
a[1][1][0] = 010100 a[1][1][1] = 010101
a[1][2][0] = 010200 a[1][2][1] = 010201
a[1][3][0] = 010300 a[1][3][1] = 010301
a[1][4][0] = 010400 a[1][4][1] = 010401
a[2][0][0] = 020000 a[2][0][1] = 020001
a[2][1][0] = 020100 a[2][1][1] = 020101
a[2][2][0] = 020200 a[2][2][1] = 020201
a[2][3][0] = 020300 a[2][3][1] = 020301
a[2][4][0] = 020400 a[2][4][1] = 020401
a[3][0][0] = 030000 a[3][0][1] = 030001
a[3][1][0] = 030100 a[3][1][1] = 030101
a[3][2][0] = 030200 a[3][2][1] = 030201
a[3][3][0] = 030300 a[3][3][1] = 030301
a[3][4][0] = 030400 a[3][4][1] = 030401
a[4][0][0] = 040000 a[4][0][1] = 040001
a[4][1][0] = 040100 a[4][1][1] = 040101
a[4][2][0] = 040200 a[4][2][1] = 040201
a[4][3][0] = 040300 a[4][3][1] = 040301
a[4][4][0] = 040400 a[4][4][1] = 040401
Run Code Online (Sandbox Code Playgroud)
将此与您所拥有的相比较.您可以添加更多诊断打印消息.如果这没有足够的帮助,请创建一个类似于此的SSCCE(简短,自包含,正确的示例),它可以在没有任何无关材料的情况下演示代码中的问题.
这是一个稍微复杂的代码版本,模拟N分配后的内存分配失败(以及运行它的测试工具,其中N的每个值从0到35,实际上只有30个数组的分配.它也是包括释放数组的代码(类似于但不同于harpun编辑到我的答案中的代码.最后与包含PID的行的交互意味着我可以ps在另一个终端窗口中检查内存使用情况.(否则,我不喜欢那些做那种事情的程序 - 我想我应该ps从我的程序中运行system(),但我感觉很懒.)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int fail_after = 0;
static int num_allocs = 0;
static void *xmalloc(size_t size)
{
if (fail_after > 0 && num_allocs++ >= fail_after)
{
fputs("Out of memory\n", stdout);
return 0;
}
return malloc(size);
}
static int ***allocate_3d_array(int no1, int ****a)
{
*a = (int***)xmalloc(no1 * sizeof(int**));
if (*a == 0)
return 0;
for (int l = 0; l < no1; l++)
{
if (((*a)[l]=(int**)xmalloc((no1+1)*sizeof(int*))) == 0)
{
for (int l1 = 0; l1 < l; l1++)
free((*a)[l1]);
free(*a);
*a = 0;
return 0;
}
}
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
if (((*a)[l][h]=(int*)xmalloc(2*sizeof(int))) == 0)
{
/* Release prior items in current row */
for (int h1 = 0; h1 < h; h1++)
free((*a)[l][h1]);
free((*a)[l]);
/* Release items in prior rows */
for (int l1 = 0; l1 < l; l1++)
{
for (int h1 = 0; h1 < no1; h1++)
free((*a)[l1][h1]);
free((*a)[l1]);
}
free(*a);
*a = 0;
return 0;
}
}
}
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
(*a)[l][h][k] = 10000 * l + 100 * h + k;
return *a;
}
static void destroy_3d_array(int no1, int ***a)
{
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
free(a[l][h]);
free(a[l]);
}
free(a);
}
}
static void test_allocation(int no1)
{
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
for (int k = 0; k < 2; k++)
{
if (a[l][h][k] != l * 10000 + h * 100 + k)
printf("a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
}
}
}
}
destroy_3d_array(no1, a);
}
int main(void)
{
int no1 = 5;
for (fail_after = 0; fail_after < 33; fail_after++)
{
printf("Fail after: %d\n", fail_after);
num_allocs = 0;
test_allocation(no1);
}
printf("PID %d - waiting for some data to exit:", (int)getpid());
fflush(0);
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意内存恢复是多么痛苦.和以前一样,没有经过测试valgrind,但我从先前版本的harpun测试中得到了保证.
valgrind此代码与版本2中的测试非常相似.它在叶级分配中的内存分配失败时修复了清理中的内存泄漏.该程序不再提示输入(更可取); 它需要一个可选的单个参数,即后面失败的分配数.测试valgrind显示,参数0-6没有泄漏,但是参数7存在泄漏.没过多久就发现问题并修复它.(当机器运行valgrind可用时,它会更容易- 在整个现场电源升级的长周末,它会被关闭.)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int fail_after = 0;
static int num_allocs = 0;
static void *xmalloc(size_t size)
{
if (fail_after > 0 && num_allocs++ >= fail_after)
{
fputs("Out of memory\n", stdout);
return 0;
}
return malloc(size);
}
static int ***allocate_3d_array(int no1, int ****a)
{
*a = (int***)xmalloc(no1 * sizeof(int**));
if (*a == 0)
return 0;
for (int l = 0; l < no1; l++)
{
if (((*a)[l]=(int**)xmalloc((no1+1)*sizeof(int*))) == 0)
{
for (int l1 = 0; l1 < l; l1++)
free((*a)[l1]);
free(*a);
*a = 0;
return 0;
}
}
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
if (((*a)[l][h]=(int*)xmalloc(2*sizeof(int))) == 0)
{
/* Release prior items in current (partial) row */
for (int h1 = 0; h1 < h; h1++)
free((*a)[l][h1]);
/* Release items in prior (complete) rows */
for (int l1 = 0; l1 < l; l1++)
{
for (int h1 = 0; h1 < no1; h1++)
free((*a)[l1][h1]);
}
/* Release entries in first (complete) level of array */
for (int l1 = 0; l1 < no1; l1++)
free((*a)[l1]);
free(*a);
*a = 0;
return 0;
}
}
}
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
(*a)[l][h][k] = 10000 * l + 100 * h + k;
return *a;
}
static void destroy_3d_array(int no1, int ***a)
{
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
free(a[l][h]);
free(a[l]);
}
free(a);
}
}
static void test_allocation(int no1)
{
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
for (int k = 0; k < 2; k++)
{
if (a[l][h][k] != l * 10000 + h * 100 + k)
printf("a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
}
}
}
}
destroy_3d_array(no1, a);
}
int main(int argc, char **argv)
{
int no1 = 5;
int fail_limit = 33;
if (argc == 2)
fail_limit = atoi(argv[1]);
for (fail_after = 0; fail_after < fail_limit; fail_after++)
{
printf("Fail after: %d\n", fail_after);
num_allocs = 0;
test_allocation(no1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更新2014-12-20
上面的代码会产生大量的内存分配,这会使发布和错误恢复变得复杂.这是一个替代版本,只有3个分配,一个用于指针指针的向量,一个用于指针数组,一个用于整数数组.然后它将指针设置为指向内存中的正确位置.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int fail_after = 0;
static int num_allocs = 0;
static void *xmalloc(size_t size)
{
if (fail_after > 0 && num_allocs++ >= fail_after)
{
fputs("Out of memory\n", stdout);
return 0;
}
return malloc(size);
}
static int ***allocate_3d_array(int no1, int ****a)
{
int ***d0 = (int***)xmalloc(no1 * sizeof(int**));
int **d1 = (int **)xmalloc(no1 * no1 * sizeof(int *));
int *d2 = (int *)xmalloc(no1 * no1 * 2 * sizeof(int));
if (d0 == 0 || d1 == 0 || d2 == 0)
{
free(d0);
free(d1);
free(d2);
*a = 0;
return 0;
}
for (int l = 0; l < no1; l++)
{
d0[l] = &d1[l * no1];
for (int h = 0; h < no1; h++)
{
d0[l][h] = &d2[(l * no1 + h) * 2];
for (int k = 0; k < 2; k++)
d0[l][h][k] = l * 10000 + h * 100 + k;
}
}
*a = d0;
return *a;
}
static void destroy_3d_array(int ***a)
{
if (a != 0)
{
free(a[0][0]);
free(a[0]);
free(a);
}
}
static void test_allocation(int no1)
{
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
for (int k = 0; k < 2; k++)
{
if (a[l][h][k] != l * 10000 + h * 100 + k)
printf("Oops: a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
}
}
}
}
destroy_3d_array(a);
}
int main(int argc, char **argv)
{
int no1 = 5;
int fail_limit = 4;
if (argc == 2)
fail_limit = atoi(argv[1]);
for (fail_after = 0; fail_after < fail_limit; fail_after++)
{
printf("Fail after: %d\n", fail_after);
num_allocs = 0;
test_allocation(no1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这与Mac OS X 10.10.1上的GCC 4.9.1有一个干净的健康状况,使用valgrind版本valgrind-3.11.0.SVN 进行检查(从SVN树构建,对Mac OS X有一些必要的修复,但没有足够的抑制) .
在我得出答案时,触发了诊断打印(以'哎呀'开头); 当时我的指针计算错了.
| 归档时间: |
|
| 查看次数: |
687 次 |
| 最近记录: |