Emily-CS 发表于 2016-4-4 12:14:34

C语言链表写入冲突

调试的显示是:
心好累啊.exe 中的 0x0115173b 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefef2 时发生访问冲突

指向出问题的地方:
int length_list (NODE *pHead)
{
        int len = 0;
        NODE *p = pHead->pNext;
        while (p != NULL)
        {
                len++;
                printf("%d",len);
                p = p->pNext;//这里显示有问题

        }
        printf("%d",len);
        return len;
}

但是为什么会这样啊?

下附整个程序:(用动态链表实现报数报到3踢出局)
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

//函数声明

struct NODE1
{
        int data;
        struct NODE1 * pNext;
};
typedef struct NODE1 NODE;
//typedef struct NODE1 * PNODE;


NODE * creat_list();
int length_list (NODE *pHead);
void delete_list(NODE *pHead, NODE *p);


int main()
{
        NODE *pHead = creat_list();
        int count = 0;
        NODE *p = pHead;
        while (length_list(pHead)>1)
        {
                p = p->pNext;
                ++ count;
                if (count == 3 && p != NULL)
                {
                        delete_list (pHead, p);
                        count = 0;
                }
                if (p == NULL)
                {
                        p = pHead;
                }
        }
        printf ("剩余的人的编号是:%d", pHead->pNext->data);
        while (1);
        return 0 ;
       
}

NODE *creat_list()
{
        NODE *pHead = (NODE * )malloc(sizeof(NODE));
        int len, data, i;
        NODE * pTail;
        printf("一共多少人玩(请输入人数):\n");
        scanf_s ("%d", &len);
        if (pHead == NULL)
        {
                printf ("分配内存失败,程序结束!");
                exit(-1);
        }
        pHead->pNext = NULL;
        pTail = pHead;

        for (i=0; i<len; i++)
        {
                NODE *pNew = (NODE * )malloc(sizeof(NODE));
                if (pNew == NULL)
                {
                  printf ("分配内存失败,程序结束!");
                  exit(-1);
                }
                pNew->pNext = NULL;
                pNew->data = i+1;
                printf("%d",pNew->data);
                pTail->pNext = pNew;
                pTail = pNew;
        }
        printf("\n%d",pHead->pNext->data);
        return pHead;
}

int length_list (NODE *pHead)
{
        int len = 0;
        NODE *p = pHead->pNext;
        while (p != NULL)
        {
                len++;
                printf("%d",len);
                p = p->pNext;

        }
        printf("%d",len);
        return len;
}

void delete_list(NODE *pHead, NODE *p)
{
        //if (pHead->pNext == NULL)
        //        return false;
        NODE *pTag = pHead->pNext; NODE *pFore = pHead;
        while (pTag != p)
        {
                pFore = pTag;
                pTag = pTag->pNext;
        }
        if (p->pNext != NULL)
        {
                pTag->pNext = p->pNext;
        }
        else pTag->pNext = NULL;
        free (p);
        p = NULL;
        //return true;
}

ryxcaixia 发表于 2016-4-6 09:22:33

p = p->pNext 出错 肯定是因为p->pNext是一个无法访问的地址
动态调试看看 单步到崩溃的时候 看看此时p->pNext的值是什么

shuofxz 发表于 2016-4-6 16:05:21

NODE *p = pHead->pNext;
这个你只是声明了一个NODE*类型的指针,但是没有在内存中给p开辟空间呀
改成
NODE *p = (NODE*)malloc(sizeof(NODE))
p = pHead->pNext;
再试试

immortalfaith 发表于 2016-9-12 12:59:11

地址错误

mingcxx 发表于 2016-9-12 20:40:42

本帖最后由 mingcxx 于 2016-9-12 20:41 编辑

感觉你的代码思路有点乱,
创建节点时从第2个节点开始录入数据,整个程序运行中头结点数据一直是不定内存,浪费内存。
删除节点时却只释放了节点所占用的内存(而没有把待删除节点的前一个节点中指向该节点的Next指针更新NULL或指向目标节点的下一节点),那你的链表中依然链接了这个节点,只不过释放内存之后,这个节点的内存不可读。p = p->pNext;自然要出错。
以及没有释放链表占用的内存。
下面是仅仅无bug的修改代码,输出的数据意义不清晰(尤其第3行),依赖具体功能和代码思路需要进一步修改:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

//函数声明

struct NODE1
{
        int data;
        struct NODE1 * pNext;
};
typedef struct NODE1 NODE;
//typedef struct NODE1 * PNODE;


NODE * creat_list();
int length_list(NODE *pHead);
void delete_list(NODE *pHead, NODE **p);


int main()
{
        NODE *pHead = creat_list();
        int count = 0;
        NODE *p = pHead;
        while (length_list(pHead)>1)
        {
                p = p->pNext;
                ++count;
                if (count == 3 && p != NULL)
                {
                        delete_list(pHead, &p);
                        count = 0;
                }
                if (p == NULL)
                {
                        p = pHead;
                }
                if (count < 3)
                        break;
        }
        printf("剩余的人的编号是:%d", pHead->pNext->data);
        while (1);
        return 0;

}

NODE *creat_list()
{
        NODE *pHead = (NODE *)malloc(sizeof(NODE));
        int len, data, i;
        NODE * pTail;
        printf("一共多少人玩(请输入人数):\n");
        scanf_s("%d", &len);
        if (pHead == NULL)
        {
                printf("分配内存失败,程序结束!");
                exit(-1);
        }
        pHead->pNext = NULL;
        pTail = pHead;

        for (i = 0; i<len; i++)
        {
                NODE *pNew = (NODE *)malloc(sizeof(NODE));
                if (pNew == NULL)
                {
                        printf("分配内存失败,程序结束!");
                        exit(-1);
                }
                pNew->pNext = NULL;
                pNew->data = i + 1;
                printf("%d", pNew->data);
                pTail->pNext = pNew;
                pTail = pNew;
        }
        printf("\n%d", pHead->pNext->data);
        return pHead;
}

int length_list(NODE *pHead)
{
        int len = 0;
        NODE *p = pHead->pNext;
        while (p != NULL)
        {
                len++;
                printf("%d", len);
                p = p->pNext;
        }
        printf("%d", len);
        return len;
}

void delete_list(NODE *pHead, NODE **p)
{
        //if (pHead->pNext == NULL)
        //      return false;
        NODE *pTag = pHead; NODE *pFore = pHead;
        while (pTag->pNext != *p)
        {
                pFore = pTag;
                pTag = pTag->pNext;
        }
        if ((*p)->pNext != NULL)
        {
                pTag->pNext= (*p)->pNext;
        }
        else
                pTag->pNext = NULL;
        free((*p));
        *p = NULL;
        //return true;
}

SingleLove 发表于 2016-9-12 21:23:17

本帖最后由 SingleLove 于 2016-9-12 21:25 编辑

问题就在你这个函数void delete_list(NODE *pHead, NODE *p)释放掉被选中的节点后;
main函数里的辅助指针找不到这个已经被释放掉的节点的地址了;所以就报错了
可以在void delete_list(NODE *pHead, NODE *p) 这个函数返回下一个节点的地址;
再用main函数里的辅助指针接一下:p = delete(pHead, p);

下面是我自己写的代码
#define _CRT_SECURE_NO_WARNINGS//我是在vs2013做的所以加了这句宏定义 防止 scanf 带来的error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//malloc() 等
#include <Windows.h>//Sleep()


//定义节点
typedef struct Node
{        //数据域
        int data;
        //指针域
        struct Node *next;

}Node;

//创建链表
Node *creatList()
{
        printf("请问有多少人玩游戏:");
        int data;
        scanf("%d", &data);

        if (data <= 0)//判断输入的数字是否合法
        {
                printf("请输入大于0的玩家个数\n");
                return NULL;
        }

        //创建头节点
        Node * head = (Node *)malloc(sizeof(Node));
        if (head == NULL)//判断是否成功分配内存
        {
                return NULL;
        }
        head->next = NULL;//头结点的指针域指向空

        Node *cur = NULL;//保存尾结点
        Node *pNew = NULL;//创建新节点

        int i = 0;//用于给节点赋值
        cur = head;//在没创建数据节点前头结点就是尾结点
        while (cur != NULL)
        {
                i++;
                if (cur->data == data)//当节点的值为data时跳出循环
                {
                        break;
                }

                pNew = (Node *)malloc(sizeof(Node));//创建新节点
                pNew->data = i;//给新节点赋值
                cur->next = pNew;//使当前节点的next指向新节点
                cur = pNew;//保存尾结点
                pNew->next = NULL;//尾结点的next指向NULL
        }

        return head;//把头节点的地址返回
}

//释放被选中的节点
Node *DelList(Node *head, Node *delNode)
{
        if (head == NULL)
        {
                return NULL;
        }
        //定义两个变量来查找这个节点和它上一个节点所在位置

        Node *pre = head;//靠前的
        Node *cur = head->next;
        while (cur != NULL)
        {
                if (cur->data == delNode->data)//找到要释放的节点
                {
                        break;
                }
                pre = pre->next;
                cur = cur->next;
        }
        //跳出循环时 cur指向delNode这个节点, pre指向delNode的上一个节点

        pre->next = cur->next;
        free(cur);
        cur = pre->next;
        return cur;//这个很重要;楼主的段错误就是因为没有把这个地址返回造成的;
        //当你把节点释放之后main函数里的辅助指针( tmp )再也找不到这个节点的地址,
        //所以就报错了
        //我返回的是被释放节点的下一个节点的地址

}

//获取剩余有效节点的个数(即剩余玩家的个数)
int listLength(Node *head)
{
        if (head == NULL)//判断传入的地址是否有效
        {
                return -1;
        }

        int i = 0;//用于计算剩余玩家的个数
        Node *tmp = head->next;//指向首节点

        printf("尚未退出游戏的玩家编号分别是:\n");
        while (tmp != NULL)
        {
               
                i++;
                printf("%d,", tmp->data);//打印剩余玩家的编号
               
                tmp = tmp->next;//跳向下一个数据节点
        }
        printf("\n");

        return i;//返回剩余玩家的个数
}


int main()
{
        while (1)//循环输入
        {
                Node *head = NULL;
                head = creatList();//接返回的地址
                if (head == NULL)//创建链表失败
                {
                        return -1;
                }

                int count = 0;//用于数数;数到3则踢出一个玩家
                Node *tmp = head->next;

                int i = listLength(head);//有多少个玩家
                while (i > 1)
                {

                        if (tmp == NULL)
                        {
                                tmp = head->next;

                        }
                        count++;
                        if (count == 3 && tmp != NULL)
                        {
                                printf("被踢出局的玩家是 %d 号玩家\n", tmp->data);
                                tmp = DelList(head, tmp);
                                i = listLength(head);
                                count = 0;
                                continue;
                        }
                        tmp = tmp->next;


                }
                //最后跳出循环肯定只剩下一个玩家没有被踢出游戏的
                tmp = head->next;//跳出循环时很可能tmp的值是NULL;
                //例如 4 的时候
                //那样就会造成段错误;所以需要重新指定下
                printf("游戏结束尚未退出游戏的玩家的编号%d\n", tmp->data);

                Sleep(3000);//让程序睡眠3秒;linux系统则是 3

                system("cls");//清屏
        }
       
        printf("\n");
        system("pause");

       
        return 0;
}

aclii 发表于 2016-9-22 22:43:39

{:10_249:}{:10_249:}感觉完全看不懂你到底想要实现什么功能{:10_249:}{:10_249:}
页: [1]
查看完整版本: C语言链表写入冲突