为什么尝试添加到count和printf时会出现Segmentation错误?

时间:2016-07-08 23:05:56

标签: c list queue

#include <stdio.h>                         /* the "QueueTypes.h" file, */
#include <stdlib.h>                   /* given above on lines 1:15, is */
#include "QueueImplementation.c"   

void main(void){
    Queue *que;
    ItemType *num;
    num = 0;
    InitializeQueue(que);
    int count = 0;
    int check;
    int i;

    if(Empty(que) != 1){
        count = count + 1;
    }
    printf("%d", count); <- segmentation fault

    if(Remove(que, num) != 0){
        count = count + 1; <- segmentation fault
}

这些是程序中不断出现分段错误的部分。我是非法访问任何东西吗?

这是queueimplementation.c。当我删除被指出的行时,程序正常工作并正常返回错误。

/*   ------------< begin file "QueueImplementation.c" >------------   */

   #include <stdio.h>                         /* the "QueueTypes.h" file, */
   #include <stdlib.h>                   /* given above on lines 1:15, is */
   #include "QueueInterface.h"          /* included in "QueueInterface.h" */
                                             /* on line 3 of Program 7.4. */

   void SystemError(char *errorMsg) {fprintf(stderr,errorMsg);}

   void InitializeQueue(Queue *Q)
   {
      Q->Front = NULL;
      Q->Rear  = NULL;
   }

 /* -------------------- */

   int Empty(Queue *Q)
   {
      return (Q->Front == NULL);
   }
 /* -------------------- */

   int Full(Queue *Q)   
   {                     /* we assume an already constructed queue, Q, is */
      return 0;              /* not full, since it could potentially grow */
   }                                             /* as a linked structure */

/* -------------------- */

   int Insert(ItemType R, Queue *Q)
   {   
      QueueNode *Temp;
                                                   /* attempt to allocate */
      Temp = (QueueNode *) malloc(sizeof(QueueNode));       /* a new node */

      if (Temp == NULL) {               /* Temp = NULL signals allocation */
         SystemError("system storage is exhausted");           /* failure */
     return 0;
      } else {
         Temp->Item = R;
         Temp->Link = NULL;
         if ( Q->Rear == NULL ) {
            Q->Front = Temp;
            Q->Rear = Temp;
         } else {
            Q->Rear->Link = Temp;
            Q->Rear = Temp;
         }
      }
      return 1;
   }

/* -------------------- */

   int Remove(Queue *Q, ItemType *F)
   {   
      QueueNode *Temp;

      if (Q->Front == NULL) {
         SystemError("attempt to remove item from empty Queue");
     return 0 ;
      } else {
         *F = Q->Front->Item;
         Temp = Q->Front;
         Q->Front = Temp->Link;
         free(Temp);
         if (Q->Front == NULL) Q->Rear = NULL;
     return 1;
      }
   }

/* -------------------- */

2 个答案:

答案 0 :(得分:2)

当您将指针que传递给InitializeQueue()时,尚未初始化指针{。}}。

更好的实现可能是将指针传递给指针que(即Queue**)到InitializeQueue()

void InitializeQueue(Queue **Q)
{
   *Q = malloc(sizeof**Q); // set aside memory for your queue
   Q->Front = NULL;
   Q->Rear  = NULL;
}

并像这样称呼它

Queue *que;
InitializeQueue(&que);

如果您无法更改QueueImplementation.c的实现,请在函数调用之前调用malloc,如下所示:

Queue *que = malloc(sizeof*que);
InitializeQueue(que);

或根本不使用堆分配(我的建议):

Queue que; // note that this is not a pointer
InitializeQueue(&que); // we have to take the address of it

请注意,使用上述选项,que只能在定义它的函数内合法访问。但是,这应该不会影响您,因为您在main中定义它,因此它将在您的程序的生命周期中存在。

对于两个malloc选项,请务必在使用完毕后致电free()

在将num传递给Remove()之前,您也无法初始化valgrind。你应该同样修复它。

您可以考虑使用if (Empty(que))之类的调试器。分段错误并不总是在导致它的同一行代码中发生(如果它们发生),并且作为一种错误检查方式可能不可靠。

P.S。使用if (Empty(que) != 1)而不是1就足够了,因为当它们求值为非零整数时,表达式为“true”。它可以说更安全,因为所有“真实”值都不一定是#include

P.P.S。不要.c .h个文件。包含.c文件并使用主程序编译gcc文件。如果您使用的是gcc myprogram.c QueueImplementation.c ,那么

<input type="button" value="Test Fire!" onclick="debugger;" />

其他编译器使用相同的语法(某处可能存在异常,但我没有遇到过)。

答案 1 :(得分:1)

在C中,当你只是声明一个指针Queue *时,它并没有神奇地指向一个新的&#34;有效的&#34;队列的实例。实际上,它指向内存中的随机位置,它很可能不包含对您有意义的任何内容。

为简化起见,在您的代码中:

  • 给我一个指针,我不在乎它指向的地方。
  • 将{NULL,NULL}放到指针指向的位置。

因此,您正在将{NULL,NULL}写入系统内存的随机部分。

这不是你怎么做的。看看Luddite提供的例子。

另外,请阅读这篇文章以了解这里发生了什么:

https://www.cs.cf.ac.uk/Dave/C/node10.html