使用双维指针分配2D数组时的Segfault

时间:2014-12-10 21:12:37

标签: c arrays pointers multidimensional-array

我目前正在处理codechef练习题http://www.codechef.com/problems/STEPUP#

我尝试使用指针设置2D数组以接受数据,并在我使用scanf接收数据时输入2D数组。

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv) 
{
    int m,n,i,k,j;
    int ex;
    scanf("%d",&ex);
    for(i=0;i<ex;i++)
    {
        int **edgegraph=NULL,temp1,temp2;
        scanf("%d %d",&n,&m);
        edgegraph=malloc(m*sizeof(int));
        for(k=0;k<m;k++)
        {
            *(edgegraph+k)=malloc(m*sizeof(int));
            if(!*(edgegraph+k))
                exit(0);
        }

        for(k=0;k<m;k++)
        {
            scanf("%d %d",&temp1,&temp2);                           
            *(*(edgegraph+m*temp1)+temp2)=1;            
        }

        for(i=0;i<m;i++)
        {
            for(j=0;j<m;j++)
                printf("%d ",*(*(edgegraph+m*i)+j));
            printf("\n");   
        }   
    }
}

我得到的错误是     (gdb)运行     启动程序:/ home / vishwa / codechef / valid     2     2 2     1 2

Program received signal SIGSEGV, Segmentation fault.
0x000000000040079d in main (argc=1, argv=0x7fffffffded8) at validedge.c:24
24                  *(*(edgegraph+m*temp1)+temp2)=1;    
(gdb) quit

我打算做的是创建一个m * m矩阵,将所有有效边设置为1,然后按边数的升序排序。我不确定这是否可以解决问题,但我想知道我在哪里弄乱。

2 个答案:

答案 0 :(得分:1)

你malloc的字节数错误:edgegraph=malloc(m*sizeof(int));应该有malloc(m * sizeof(int *));。要避免此类错误,您可以使用以下模式:

ptr = malloc( N * sizeof *ptr );

总是分配N的任何ptr是指针。

接下来,语法x[y]*(x+y)更容易阅读,特别是当表达式变得复杂时。使用该语法可以避免错误dconman指出。您似乎已在计算中添加了额外的m *,而不是必需的。

您稍后会在代码中混淆mn。要避免此类错误,请使用更具描述性的变量名称。


因此,分配代码的固定版本可能如下所示:

if ( 2 != scanf("%d %d",&num_edges, &num_vertices) )
    exit(EXIT_FAILURE);

edgegraph = malloc( num_vertices * sizeof *edgegraph );

for (int vertex = 0; vertex < num_vertices; ++vertex)
{
    edgegraph[vertex] = malloc( num_vertices * sizeof **edgegraph );
    if ( edgegraph[vertex] == NULL )
        exit(EXIT_FAILURE);
}

请注意,可以使用单个分配替换malloc系列:

int (*edgegraph)[num_vertices] = malloc( num_vertices * sizeof *edgegraph );

转到代码上读取边缘。您写了for(k=0;k<m;k++),但我认为您的意思是n。使用更具描述性的变量名称和x[y]语法:

for(int edge = 0; edge < num_edges; ++edge)
{
    if ( 2 != scanf("%d %d",&temp1,&temp2) )
         exit(EXIT_FAILURE);

    if ( temp1 < 0 || temp1 >= num_vertices || temp2 < 0 || temp2 >= num_vertices )
         exit(EXIT_FAILURE);   // maybe display an error message

    edgegraph[temp1][temp2] = 1;
    edgegraph[temp2][temp1] = 1;   // add this if undirected graph!
}

现在是最后一个循环,for(i=0;i<m;i++)。您已使用相同的变量i作为此循环的控制变量以及外部循环。要避免此类错误,请使用范围控制变量:

for (int i = 0; i < num_edges; ++i)

最后,您需要在外循环的每一次结束时释放malloc&#39; d。

答案 1 :(得分:0)

*(*(edgegraph+m*temp1)+temp2)=1;

应该是

*(*(edgegraph+temp1)+temp2)=1;

在您的代码中稍后执行该操作的相同更改。 您是否有理由不使用数组索引?

修改

这是我的输入

2
10
10
4 3
4 9
7 3
3 7
4 3
4 5
7 4
3 5
9 0
5 2

我得到了这个输出

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 1 0 1 0 0 
0 0 0 1 0 1 0 0 0 1 
0 0 1 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 1 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
1 0 0 0 0 0 0 0 0 0