VS引发异常:读取访问权限冲突。指针p2是nullptr

要写一个职工工资管理系统,通过链表实现,现在想写一个函数给链表中的结点排序(按编号顺序排:1、2、3等),
但在该排序函数fun_sort碰到了如下报错,称p2是nullptr。
如图:

img

该项目的结构定义:

typedef struct staff {
    int num;            /* 职工编号 */
    char name[20];        /* 姓名 */
    char dept[50];        /* 所属部门 */
    double S[MAXI];         /* 工资项目数组,与数组 ITEM[MAXI]的标号对应,0~49*/
    double total;        /* 工资合计 */
    struct stuff *next;
}EMPLOYEE;

主函数中的全局变量:

EMPLOYEE* head = NULL, * tail = NULL;
char ITEM[MAXI][20];
int count1 = -1;        /*项目数量计数*/ /*count1 +1 是真实的项目数量*/
int count_staffnum = 0;        /*职工数量统计*/

主函数中建立链表的函数与排序函数的关系:

fun11();
fun_sort();

建立链表的函数fun11():

void fun11()    /*新增职工信息记录*/
{
    EMPLOYEE* p;
    int num=0;
    char name[20] = { 0 };
    char dept[50] = { 0 };
    printf("\n");
    printf("请依次输入职工编号、姓名、所属部门\n");
    printf("如:01 张三 财务\n");
    printf("返回上一级请输入0\n");
    printf(">>");
    scanf("%d", &num);
    if (num != 0) 
    {
        scanf("%s", name);
        scanf("%s", dept);
        p = (EMPLOYEE*)malloc(sizeof(EMPLOYEE));
        p->num = num;
        strcpy(p->name, name);
        strcpy(p->dept, dept);
        if (head == NULL)
        {
            head = p;
        }
        else
        {
            tail->next = p;
        }
        tail = p;
        tail->next = NULL;
        printf("\n");
        printf("%02d %s %s    已添加成功", p->num, p->name, p->dept);
        count_staffnum++;
        printf("\n");
    }
}

对链表结点进行顺序排序的函数fun_sort():

int fun_sort()
{
    EMPLOYEE* p1, * p2, * p3;
    p1 = NULL;
    p2 = NULL;
    p3 = NULL;
    int cnt = 0;
    int num2, num3;
    p1 = head;
    p2 = head;
    if (p1 != NULL && p2 != NULL)
    {
        if (p2->next == NULL)    /*判断函数是否只有一个结点,是的话直接返回*/
        {
            return 0;
        }
        else
        {
            p3 = p2->next;
            do 
            {
                if (cnt != 0) /*第二次及以后进入do-while循环时让所有指针都向后移动*/
                {
                    p1 = p2;
                    p3 = p3->next;
                    p2 = p2->next;
                }
                num2 = p2->num;
                num3 = p3->num;
                if (num2 > num3)
                {
                    if (p2 == head) /*头结点交换*/
                    {
                        if (p3->next == NULL) /*结点只有两个*/
                        {
                            p3->next = p2;
                            head = p3;
                            p2->next = NULL;
                        }
                        else /*结点不止两个*/
                        {
                            p1 = p3->next;
                            p3->next = p2;
                            head = p3;
                            p2->next = p1;
                        }
                    }
                    else /*非头结点交换*/
                    {
                        if (p3->next == NULL) /*交换的结点有一个是链表的尾端*/
                        {
                            p3->next = p2;
                            p2->next = NULL;
                            p1->next = p3;
                        }
                        else /*交换的结点在链表中间*/
                        {
                            p2->next = p3->next;
                            p1->next = p3;
                            p3->next = p2;
                        }
                    }
                }
                cnt++;
            } while (p3->next != NULL);
            p1 = NULL;
            p2 = NULL;
            p3 = NULL;
            return 0;
        }
    }
}

这是不是排序函数有问题?还是建立链表的函数有问题?

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633