C 导致访问冲突的指针逻辑

C 导致访问冲突的指针逻辑,c,pointers,memory-management,data-structures,C,Pointers,Memory Management,Data Structures,添加联系人的程序方法之一是在执行时出现以下错误: Unhandled exception at 0x00111deb in G00290342.exe: 0xC0000005: Access violation reading location 0x00000050. 我研究了这个错误,发现它是由访问已经在使用的内存引起的。我已经把它缩小到readFile方法中导致“curr”变量为空的指针逻辑 它正在破坏的代码如下所示: while(curr->next != NULL) {

添加联系人的程序方法之一是在执行时出现以下错误:

Unhandled exception at 0x00111deb in G00290342.exe: 0xC0000005: Access violation reading location 0x00000050.
我研究了这个错误,发现它是由访问已经在使用的内存引起的。我已经把它缩小到readFile方法中导致“curr”变量为空的指针逻辑

它正在破坏的代码如下所示:

while(curr->next != NULL)
    {
        curr = curr->next;

    }
这是供参考的完整方法:

int addContact(struct contact *theList)
{
    struct contact *newContact, *curr;
    char fn[15],sn[15],ph[15],cmpy[15],eml[15];

    //create the new structure
    newContact = (struct contact *)malloc(sizeof(struct contact));
    if(newContact == NULL)
    {

        return(0);

    }
    //find the end of list
    curr = theList;
    //scroll through the list
    while(curr->next != NULL)
    {
        curr = curr->next;

    }
    //now have the last contact and the new one here
    printf("\nEnter a surname: ");
    gets(newContact->sname);

    printf("\nEnter a first name: ");
    gets(newContact->fname);

    printf("\nEnter a phone: ");
    gets(newContact->phone);

    printf("\nEnter a company: ");
    gets(newContact->company);

    printf("\nEnter an email: ");
    gets(newContact->email);

    //add the new contact to the end of the list

    curr->next = newContact;
    newContact->prev = curr;
    newContact->next = NULL;
    return(0);


}//end addContact
这是我读取测试文件的主要方法:

main()
{
    int sts,iChoice;
    struct contact *ptrList, *head;

    //head of sorted list
    struct contact *srtdList;

    srtdList = NULL;
    ptrList = NULL;

    ptrList = readFile("test.csv",ptrList);
    head = ptrList;

    /////menu for options
    system("cls");
    printf("\n\n\t\tWelcome to BV Contact Organizer\n\n");
    printf("\n\n\t\tEnter a number ranging from 1 to 6 for options.\n\n");
    printf("\n\t\t1. Search");
    printf("\n\t\t2. Add");
    printf("\n\t\t3. Sort");
    printf("\n\t\t4. Remove");
    printf("\n\t\t5. Edit");
    printf("\n\t\t6. Exit");
    printf("\n\n\t\tEnter your menu choice: ");
    fflush(stdin);
    scanf("%d", &iChoice);

    // user enters one of 6 values:
    // Search,add,sort,remove,exit or edit contacts


    switch(iChoice)
    {

        case 1:     // Add
        {
            sts = addContact(head);
            sts = writeListToFile("test.csv",head);
            while(ptrList != NULL)
            {
                printf("\n%s,%s,%s,%s,%s",ptrList->sname,ptrList->fname,ptrList->phone,ptrList->company,ptrList->email);
                ptrList = ptrList->next;

            }

            break;
        }
        case 2:     // Sort
        {
            //return the head of the sorted list to here
            srtdList = sortList(head,srtdList);
            head = srtdList;
            if(srtdList != NULL)
            {

                printf("\n\nSorted List");
                while(srtdList != NULL)
                {
                    printf("\n%s,%s,%s,%s,%s",srtdList->sname,srtdList->fname,srtdList->phone,srtdList->company,srtdList->email);
                    srtdList = srtdList->next;

                }

                sts = writeListToFile("testSort.csv",head);

            }
            else
            {
                printf("nothing to print");

            }
            printf("\n\n\n");
            system("pause");
            break;
        }
        case 3:     // Exit
        {
            printf("\n\nProgram exiting!...");
            break;
        }
        default:
        {
            printf("\n\nInvalid menu choice,please choose a number ranging from 1 to 6!...");
        }

    }//end of switch


    return(iChoice);

} // end of main
这是请求的结构联系人定义:

struct contact {
        char sname[15];
        char fname[15];
        char phone[15];
        char company[15];
        char email[15];
        struct contact *prev;
        struct contact *next;
};
这是用于读取文件的方法,导致以下问题:

struct contact *readFile(char * FName,struct contact *ptrList)
{

struct contact *head, *newContact;
FILE *fptr;
char oneLine[60];
char *sname, *fname, *phone,*company, *email;

head = ptrList;

fptr = fopen(FName,"r");

if(fptr == NULL)
{
    printf("\nCant open file!");
    return(ptrList);

}

fgets(oneLine, 55, fptr);
while(!feof(fptr))
{
    fgets(oneLine, 55, fptr);
    if(oneLine[strlen(oneLine)-1] == '\n')
    {
        oneLine[strlen(oneLine)-1] = '\0';

    }

    sname = strtok(oneLine,",");
    fname = strtok(NULL,",");
    phone = strtok(NULL,",");
    company = strtok(NULL,",");
    email = strtok(NULL,",");

    if(head == NULL)
    {
        head = (struct contact *)malloc(sizeof(struct contact));
        ptrList = head;
        strcpy(head->sname,sname);
        strcpy(head->fname,fname);
        strcpy(head->phone,phone);
        strcpy(head->company,company);
        strcpy(head->email, email);

        head->prev = NULL;
        head->next = NULL;


    }
    else
    {

        newContact = (struct contact *)malloc(sizeof(struct contact));
        head->next = newContact;
        newContact->prev = head;
        newContact->next = NULL;
        //copy the data to the new one
        strcpy(head->sname,sname);
        strcpy(head->fname,fname);
        strcpy(head->phone,phone);
        strcpy(head->company,company);
        strcpy(head->email,email);

        //move down the list so that the head variable
        //points to the last contact
        head = newContact;

    }

  }//end while

  fclose(fptr);
  return(ptrList);
}

它显示
访问冲突读取位置0x00000050
,因此您试图读取的内存位置实际上是一些垃圾值。从一开始就跟踪列表值,无论您在哪里分配内存,都要立即执行
memset(newContact,0,sizeof(struct contact))
。在所有这些之后,如果您仍然面临问题,请提供代码,可能存在逻辑问题

,因此您将
curr
分配给
列表
,而不进行任何
NULL
检查:

curr = theList;
因此,当您到达
时,如果
curr
确实为
NULL
,则当您尝试执行
curr->next
时,将发生访问冲突:

while(curr->next != NULL)
{
    curr = curr->next;
}

如果列表中的最后一个元素
非空
并且指向垃圾内存位置

您确定
curr
不是
吗?因为它看起来就是这样的。这里的
0x00000050
NULL
之间似乎有一些偏移。您没有检查“列表”是否为NULL。如果是,while循环将失败。至少要声明它。在尝试遍历该列表之前,您可能需要检查该列表是否为空,因为新分配的节点应该成为新的列表头(如果为空)。此外,由于报告的值不是
0x00000000
,很可能您没有正确地将列表头初始化为NULL,这是另一个逻辑错误。最后,您需要通过地址(意味着双指针)传入列表头,或者始终返回真正的列表头作为函数结果,否则您将永远无法正确设置外部列表头。。似乎这还不够,不要使用
get()
。该函数在安全性方面非常糟糕,已从该语言中弃用,将不会包含在下一个标准中。改用
fgets()
。因为你正在更新你的问题帖子,你是否也可以添加
struct contact
的结构定义?@WhozCraig我认为它是
0x00000050
,因为这是
contact
对象中
next
的偏移量。这是我的答案:)-你的在prettier中,尽管+1Ya,我刚刚在curr=theList上添加了一个空检查;我的第二个问题是如何补救?@user2307951很难说,但我猜在
readFile
中,您无法打开文件,返回
ptrList
,它是
NULL
,但是
addContact
中应该有逻辑创建
head
的位置,如果它没有初始化为Zcraig所说的您需要将
list
作为双指针传递才能工作。读取
readFile()
,将现有列表传递到函数中时会发生什么
head
最初将被设置为
ptrList
,它可能有一个
next
指向列表的其余部分。然后,在第一个节点读取时,
head->next=newContact
孤立所有经过初始
ptrList
节点的内容,从而丢失(并泄漏)这些节点。您可能也想解决这个问题,或者不必费心让函数修改现有列表,只需删除
ptrList
。正如目前所写的,它无论如何都不起作用。我不确定如何实现它?因此,它源于我的“readFile”方法。如果我去掉“ptrList”,我该怎么做?我尝试了memset代码段,但我得到一个错误,说类型contact的参数与类型int不兼容。我已经用我上面阅读列表的主方法更新了我的问题。对不起,键入:)在memset中我添加了memset代码段再次在mem分配之后。这个代码段到底是做什么的?如果您添加空检查,您将确保能够正确地检测到空列表或列表结尾。在方法的末尾,您添加了
newContact->next=NULL这使得这成为可能。现在,memset将malloc分配的整个内存设置为0。因此,即使您错过了它或其他一些地方,您可能仍然错过了它,memset已经对此进行了补偿,并且您的空检查仍然有效。基本上这是一个故障安全机制。酷,我刚刚在那里测试了它,它说“curr”没有初始化。我如何解决这个问题?好的,我解决了这个问题,结果是我的readFile方法,因为指针没有正确初始化。你能发现我的指针哪里出错了吗?上面的代码中有多个问题。1.在
readFile
else块
中,应将姓名、电话公司等的新值分配给
newContact
而不是
head
。2.在返回之前,您从未将任何内容分配给
ptrList
。因此
method
总是返回
null
。这会导致内存问题
curr = theList;    
 while(curr->next != NULL)
 {
    curr = curr->next;

}