C语言 下面链表程序分段故障的根本原因是什么?



下面是向升序链表中添加新节点的程序。

下面的程序有bug,导致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();
      }

表达式

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

将首先计算逻辑或的左侧,如果为假,则计算右侧。这意味着如果temp->linkNULL,那么你有未定义的行为当你解引用一个NULL指针。

所做的更改是改变逻辑或表达式中两个子表达式的求值顺序,因此首先检查temp->link不是NULL,然后取消对temp->link的引用。

当你这样做时-

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

temp -> link -> data中,如果temp -> link等于或当temp -> link等于NULL,则该表达式变为NULL -> data。你正在尝试解引用NULL。所以你会得到segmentation fault .

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

在这种情况下,你不会得到分割错误。因为当temp -> linkNULL条件为真时,程序执行进入循环体。所以你不会得到segmentation fault。但是当temp -> link不是NULL时,它将取消对它的引用。

在if语句的第二个版本中,短路求值将确保temp->link永远不会被解引用。

最新更新