以下链接列表程序的分段错误的根本原因是什么?

时间:2014-08-11 10:20:33

标签: c linked-list singly-linked-list

以下是将新节点添加到升序链表的程序。

以下程序中存在导致segmentation Fault的错误,我使用gdb找出了细分错误的原因。

但我没有得到reason的分段错误。任何人都可以说出分段错误的原因。

  #include<stdio.h>
  #include<stdlib.h>

  struct node
 {
     int data ;
     struct node *link ;
 } ;

 void add ( struct node **, int ) ;
 void display ( struct node * ) ;

 int  main( )
{
       struct node *p ;
        p = NULL ;  

    add ( &p, 5 ) ;
    add ( &p, 1 ) ;
    add ( &p, 6 ) ;
    add ( &p, 4 ) ;
    add ( &p, 7 ) ;


    display ( p ) ;

}


void add ( struct node **q, int num )
{
    struct node *r, *temp = *q ;

    r = ( struct node *)  malloc ( sizeof ( struct node ) ) ;
    r -> data = num ;


  if ( *q == NULL || ( *q ) -> data > num )
 {
    *q = r ;
    ( *q ) -> link = temp ;
 }
 else
 {
    while ( temp != NULL )
    {
        if ( temp -> data <= num && ( temp -> link -> data > num || 
                                    temp -> link == NULL ))
        {
            r -> link = temp -> link ;
            temp -> link = r ;
            return ;
        }
        temp = temp -> link ;  
    }
  }
}


void display ( struct node *q )
{
    printf ( "\n" ) ;


    while ( q != NULL )
    {
        printf ( "%d ", q -> data ) ;
       q = q -> link ;
    }
}

我从

改变了这一行的顺序
if ( temp -> data <= num && ( temp -> link -> data > num || temp -> link == NULL ))
//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

if ( temp -> data <= num && ( temp -> link == NULL || temp -> link -> data > num  ))
//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

以上改变的工作就像一个魅力但是我得到了这种变化背后的理由。

帮助我找出原因

**已更新

如果短路评估是真正的原因那么下面的程序为何会起作用

      int main()
     {

       int a=10,b=1,c=0;
       int d;
       d = (a && (c || b));

       printf("%d",d);
      getchar();
      }

3 个答案:

答案 0 :(得分:1)

表达式

temp -> link -> data > num || temp -> link == NULL

将首先评估逻辑的左侧,或者如果它是假的,则将评估右侧。这意味着如果temp->linkNULL,那么当您取消引用NULL指针时,您就会undefined behavior

更改的作用是更改逻辑或表达式中两个子表达式的评估顺序,因此首先检查temp->link不是NULL,然后取消引用temp->link

答案 1 :(得分:1)

当你这样做时 -

if ( temp -> data <= num && ( temp -> link -> data > num || temp -> link == NULL ))

temp -> link -> data中,如果temp -> link等于或temp -> linkNULL,则表示此表达式为NULL -> data。您正试图取消引用NULL。所以你会得到segmentation fault

if ( temp -> data <= num && ( temp -> link == NULL || temp -> link -> data > num  ))

在这种情况下,您不会出现分段错误。因为当temp -> link NULL条件成立时,程序执行进入循环体。所以你不会在这里得到segmentation fault。但是当temp -> link不是NULL时,它会取消引用它。

答案 2 :(得分:0)

在if语句的第二个版本中,short-circuit evaluation将确保temp->link永远不会被解除引用。