注释行上的Segfaults:

时间:2014-12-18 19:34:47

标签: c pointers segmentation-fault

我试图解决Codechef上的问题。我之前已经发布了相关内容,但完全不同。

http://www.codechef.com/problems/STEPUP#

问题的概念是确定给定的测试用例是否出现所需的情况。 期望的情况是每个顶点具有比连接到它的顶点更高的间接。 IE浏览器。如果a-> b,则F(b)应> F A)。如果给定设置不可能,则输出是不可能的。如果不是,则输出具有最大间接的顶点X的最小值F(x),使得它适用于所有其他顶点。 我还没有尝试为可能的情况打印输出。

输入格式:

第一行输入包含数字t,测试用例数。

每个测试用例包含以两个空格分隔的整数N和M开头,分别表示图中的顶点数和边数。

以下M行中的每一行包含两个空格分隔的整数,b表示从顶点a到顶点b的边。

两个顶点a和b之间可以有多条边。 例如,

2

2 2

1 2

2 1

3 2

1 2

1 3

OUTPUT应为:

IMPOSSIBLE

2

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Node{
 int val;
 struct Node* next;
};

int indirection[10001];//indirection[a] holds count. What vertex it holds count OF is     given by list[a].val;

int main()
{
 int testcases, num_vertices, num_edges, a,b,c,d,e;
 scanf("%d", &testcases);
 while(testcases--)
    {
        scanf("%d %d",&num_vertices, &num_edges);
        struct Node *list[num_vertices];//array of pointers to node
        int h;
        struct Node * ptr;
        for(h=1;h<=num_vertices;h++)
           {
            list[h]=(struct Node *)malloc(sizeof(struct Node));
            list[h]->val=0;
           }
        memset(indirection,0,10001);
        for(e=0;e<10001;e++)
            printf("Indirection[e]=%d \n",indirection[e]);

        a=1;
        while(a<=num_edges)
        {
            printf("messge printing for the %dth time\n",a);
             scanf("%d %d",&b,&c);
             printf("Message recd %d \n",indirection[c]);
             if(indirection[c]==0)   
                { 
                    printf("entered case1\n");
                     list[a]->val=c;
                     printf("S\n");
                       //Segfaults here
                    list[a]->next->val=b;
                     printf("SS\n");
                     indirection[a]=1;
                     ptr=list[a]->next;
                     printf("SSS \n");
                     printf("case1\n");
                }
             else
                 {  printf("entered case2\n");
                    indirection[c]++;
                     //segfaults here if i comment out the previous one
                     ptr->next->val=b;
                     printf("case2\n");
                     ptr=ptr->next;

                }
            a++;
         }

         int tra,i;
         struct Node *ptr1,*ptrnext;
         for(i=1;i<=num_edges;i++)
         {
            ptr1=list[i];
            ptrnext=list[i]->next;
            {
                if (indirection[ptr1->val]<indirection[ptrnext->val])
                     {   printf("IMPOSSIBLE");
                         break;
                      }

               else
                    {   
                        ptr1=ptrnext;
                        ptrnext=ptrnext->next;
                    }


            }

          }
          free(list);
    }
}

我在评论中提到段错误的两个陈述就在(我认为)有问题的陈述之前。如果我删除第一个,第二个段错误。如果我同时删除了这两个段落,那么无论如何。

仍在努力解决这个问题,以便我可以继续推进下一个问题。谢谢!

4 个答案:

答案 0 :(得分:2)

num_vertices被视为基于1而不是基于

    struct Node *list[num_vertices];//array of pointers to node
    int h;
    struct Node * ptr;

    // for(h=1;h<=num_vertices;h++)
    for(h=0;h<num_vertices;h++)

       {
        list[h]=(struct Node *)malloc(sizeof(struct Node));
        list[h]->val=0;
       }

next字段未按Daniel

的回答进行初始化
       {
        list[h]=(struct Node *)malloc(sizeof(struct Node));
        list[h]->val = 0;
        list[h]->next = something_maybe_NULL();
       }

建议更简单的malloc()样式

        list[h] = malloc(sizeof *(list[h]));

答案 1 :(得分:1)

您的代码段错误,因为您创建了一个struct Node*数组并为它们分配内存,但您从未设置每个next的{​​{1}}指针。因此,当您尝试访问时,每个Node的{​​{1}}指针只是指向内存中的随机位置和段错误。

我认为你的设计是错的。如果您正在尝试创建节点的链接列表(如下一个指针的存在所示),您根本不需要创建一个数组来保存节点。

答案 2 :(得分:1)

我分析了你的所有代码并发现了几个问题,这些问题主要表明你不理解指针

  1. 数组是0 - 基于索引的

    /* if you declare, struct list[size];
     * index goes from 0 ti szie - 1
     */
    for (h = 1 ; h <= num_vertices ; h++)
    {
    
  2. 您永远不会初始化node->next指针

    /* You should initialize the next node to null. */
    list[h]->next = NULL;
    
  3. 您的memset错误,sizeof(int) != 1

    /* memset(indirection, 0, 10001); wrong */
    memset(indirection, 0, 10001 * sizeof(int));
    
  4. 访问indirection数组

    时,不检查溢出
    /* this is very unsafe, you don't check c */
    printf("Message recd %d \n", indirection[c]);
    
  5. 您取消引用node->next而不检查NULL

    /* don't dereference list[a]->next without checking . 
     * list[a]->next->val (wrong) 
     */
    next = list[a]->next;
    if (next != NULL)
        next->val = b;
    
  6. free list,它是一个数组而非指针,因此您无法在其上调用free,但是,您应该free其元素,因为它们是有效malloc内存的指针

    for (i = 0 ; i < num_vertices ; i++)
        free(list[i]);
    
  7. 以下是修复此问题的代码版本,我不知道您的算法是否有效,但代码的错误至少减少了6个。

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    /* no need for typedef, since you declare as struct Node */
    struct Node
    {
        int          val;
        struct Node* next;
    };
    
    int indirection[10001];//indirection[a] holds count. What vertex it holds count OF is     given by list[a].val;
    
    int main()
    {
        int testcases, num_vertices, num_edges, a, b, c;
    
        printf("input testcase: ");
        scanf("%d", &testcases);
        while (testcases--)
        {
            printf("input testcase num_vertices and num_edges: ");
            scanf("%d %d",&num_vertices, &num_edges);
    
            int          h;
            struct Node *list[num_vertices]; // array of pointers to node
            struct Node *ptr;
    
            /* struct list[size];
                * index goes from 0 ti szie - 1
                */
            for (h = 0 ; h < num_vertices ; h++)
            {
                /* If this is plain C you don't need the cast (struct Node *) */
                list[h]      = malloc(sizeof(struct Node));
                list[h]->val = 0;
                /* You should initialize the next node to null. */
                list[h]->next = NULL;
            }
            /* memset(indirection, 0, 10001); wrong */
            memset(indirection, 0, 10001 * sizeof(int));
    
            /* What, you dont believe all values are 0? */
            /* for(e = 0 ; e < 10001 ; e++)
                printf("Indirection[e] = %d\n",indirection[e]); */
    
            /* arrays go from 0 ti size - 1 */
            a = 0;
            while (a < num_edges)
            {
                printf("messge printing for the %dth time\n", a);
    
                printf("input b and c: ");
                scanf("%d %d", &b, &c);
    
                if (c < 10001)
                {
                    /* this is very unsafe, you don't check c */
                    printf("Message recd %d \n", indirection[c]);
                    if (indirection[c]==0)
                    {
                        struct Node *next;
                        printf("entered case1\n");
    
                        list[a]->val = c;
                        printf("S\n");
    
                        // Segfaults here
                        /* don't dereference list[a]->next without checking . */
                        next = list[a]->next;
                        if (next != NULL)
                            next->val = b;
                        printf("SS\n");
    
                        indirection[a] = 1;
                        ptr            = list[a]->next;
    
                        printf("SSS \n");
                        printf("case1\n");
                    }
                    else
                    {
                        printf("entered case2\n");
                        indirection[c]++;
    
                        //segfaults here if i comment out the previous one
                        ptr->next->val=b;
    
                        printf("case2\n");
                        ptr=ptr->next;
                    }
                    a++;
                }
            }
    
            int          i;
            struct Node *ptr1, *ptrnext;
    
            for(i = 0 ; i < num_edges ; i++) /* arrays go from 0 ti size - 1 */
            {
                ptr1 = list[i];
                if (ptr1 != NULL)
                    ptrnext = ptr1->next;
                if ((ptr1 != NULL) && (ptrnext != NULL))
                {
                    if (indirection[ptr1->val] < indirection[ptrnext->val])
                    {
                        printf("IMPOSSIBLE");
                        break;
                    }
                    else
                    {
                        ptr1    = ptrnext;
                        ptrnext = ptrnext->next;
                    }
    
                }
            }
    
            for (i = 0 ; i < num_vertices ; i++)
                free(list[i]);
        }
        return 0;
    }
    

答案 3 :(得分:0)

代码

list[a]->next->val=b;

list[a]->next也许NULL。 IMO,最好在解除引用之前进行NULL检查。

中的ptr->next也是如此
ptr->next->val=b;

然而,在使用之前,您需要将内存分配给next。否则,它会指向一些 未知内存位置。

另外,为什么不从<{p>中的0开始循环

for(h=1;h<=num_vertices;h++)

旁注:请不要转换malloc()的返回值。

相关问题