鱼C论坛

 找回密码
 立即注册
查看: 3807|回复: 6

C语言链表写入冲突

[复制链接]
发表于 2016-4-4 12:14:34 | 显示全部楼层 |阅读模式
3鱼币
调试的显示是:
心好累啊.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;
}

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-4-6 09:22:33 | 显示全部楼层
p = p->pNext 出错 肯定是因为p->pNext是一个无法访问的地址
动态调试看看 单步到崩溃的时候 看看此时p->pNext的值是什么
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-4-6 16:05:21 | 显示全部楼层
  1. NODE *  p = pHead->pNext;
复制代码

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

再试试
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-9-12 12:59:11 | 显示全部楼层
地址错误
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-9-12 20:40:42 | 显示全部楼层
本帖最后由 mingcxx 于 2016-9-12 20:41 编辑

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

  4. //函数声明

  5. struct NODE1
  6. {
  7.         int data;
  8.         struct NODE1 * pNext;
  9. };
  10. typedef struct NODE1 NODE;
  11. //typedef struct NODE1 * PNODE;


  12. NODE * creat_list();
  13. int length_list(NODE *  pHead);
  14. void delete_list(NODE *  pHead, NODE **  p);


  15. int main()
  16. {
  17.         NODE *  pHead = creat_list();
  18.         int count = 0;
  19.         NODE *  p = pHead;
  20.         while (length_list(pHead)>1)
  21.         {
  22.                 p = p->pNext;
  23.                 ++count;
  24.                 if (count == 3 && p != NULL)
  25.                 {
  26.                         delete_list(pHead, &p);
  27.                         count = 0;
  28.                 }
  29.                 if (p == NULL)
  30.                 {
  31.                         p = pHead;
  32.                 }
  33.                 if (count < 3)
  34.                         break;
  35.         }
  36.         printf("剩余的人的编号是:%d", pHead->pNext->data);
  37.         while (1);
  38.         return 0;

  39. }

  40. NODE *  creat_list()
  41. {
  42.         NODE *  pHead = (NODE *)malloc(sizeof(NODE));
  43.         int len, data, i;
  44.         NODE * pTail;
  45.         printf("一共多少人玩(请输入人数):\n");
  46.         scanf_s("%d", &len);
  47.         if (pHead == NULL)
  48.         {
  49.                 printf("分配内存失败,程序结束!");
  50.                 exit(-1);
  51.         }
  52.         pHead->pNext = NULL;
  53.         pTail = pHead;

  54.         for (i = 0; i<len; i++)
  55.         {
  56.                 NODE *  pNew = (NODE *)malloc(sizeof(NODE));
  57.                 if (pNew == NULL)
  58.                 {
  59.                         printf("分配内存失败,程序结束!");
  60.                         exit(-1);
  61.                 }
  62.                 pNew->pNext = NULL;
  63.                 pNew->data = i + 1;
  64.                 printf("%d", pNew->data);
  65.                 pTail->pNext = pNew;
  66.                 pTail = pNew;
  67.         }
  68.         printf("\n%d", pHead->pNext->data);
  69.         return pHead;
  70. }

  71. int length_list(NODE *  pHead)
  72. {
  73.         int len = 0;
  74.         NODE *  p = pHead->pNext;
  75.         while (p != NULL)
  76.         {
  77.                 len++;
  78.                 printf("%d", len);
  79.                 p = p->pNext;
  80.         }
  81.         printf("%d", len);
  82.         return len;
  83. }

  84. void delete_list(NODE *  pHead, NODE **  p)
  85. {
  86.         //if (pHead->pNext == NULL)
  87.         //        return false;
  88.         NODE *  pTag = pHead; NODE *  pFore = pHead;
  89.         while (pTag->pNext != *p)
  90.         {
  91.                 pFore = pTag;
  92.                 pTag = pTag->pNext;
  93.         }
  94.         if ((*p)->pNext != NULL)
  95.         {
  96.                 pTag->pNext= (*p)->pNext;
  97.         }
  98.         else
  99.                 pTag->pNext = NULL;
  100.         free((*p));
  101.         *p = NULL;
  102.         //return true;
  103. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 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);

下面是我自己写的代码

  1. #define _CRT_SECURE_NO_WARNINGS//我是在vs2013做的所以加了这句宏定义 防止 scanf 带来的error
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>//malloc() 等
  5. #include <Windows.h>//Sleep()


  6. //定义节点
  7. typedef struct Node
  8. {        //数据域
  9.         int data;
  10.         //指针域
  11.         struct Node *next;

  12. }Node;

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

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

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

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

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

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

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

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

  58.         Node *pre = head;//靠前的
  59.         Node *cur = head->next;
  60.         while (cur != NULL)
  61.         {
  62.                 if (cur->data == delNode->data)//找到要释放的节点
  63.                 {
  64.                         break;
  65.                 }
  66.                 pre = pre->next;
  67.                 cur = cur->next;
  68.         }
  69.         //跳出循环时 cur指向delNode这个节点, pre指向delNode的上一个节点

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

  77. }

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

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

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

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


  99. int main()
  100. {
  101.         while (1)//循环输入
  102.         {
  103.                 Node *head = NULL;
  104.                 head = creatList();//接返回的地址
  105.                 if (head == NULL)//创建链表失败
  106.                 {
  107.                         return -1;
  108.                 }

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

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

  114.                         if (tmp == NULL)
  115.                         {
  116.                                 tmp = head->next;

  117.                         }
  118.                         count++;
  119.                         if (count == 3 && tmp != NULL)
  120.                         {
  121.                                 printf("被踢出局的玩家是 %d 号玩家\n", tmp->data);
  122.                                 tmp = DelList(head, tmp);
  123.                                 i = listLength(head);
  124.                                 count = 0;
  125.                                 continue;
  126.                         }
  127.                         tmp = tmp->next;


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

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

  135.                 system("cls");//清屏
  136.         }
  137.        
  138.         printf("\n");
  139.         system("pause");

  140.        
  141.         return 0;
  142. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-9-22 22:43:39 | 显示全部楼层
感觉完全看不懂你到底想要实现什么功能
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-11 12:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表