一个关于链表操作的有关问题。程序运行出错 求大神解答啊

一个关于链表操作的问题。程序运行出错 求大神解答啊!!
直接上代码!
本程序是录入一些学生的学号和姓名到链表中, 并且进行增删改查的功能, 改还没写呢

#include <stdio.h>  
#include <stdlib.h>  
#include <malloc.h> 
#include <string.h>
 
typedef struct student
{
int number;
char name[20];
struct student *link;
}stud;
stud * creat(int n);  //创建链表的函数
stud * search(stud *h);          //查询函数
void * insert(stud *p);     //插入函数,在指针p后插入
void del (stud *h); //删除函数         

int main()
{
int n,val;
stud *head;
stud *searchpoint,searchpoint2;
printf("请输入您要录入信息的数量:");
scanf ("%d", &n);
getchar();
head = creat(n);

search(head);

insert(head);

del (head);

search(head); //目的检测是否删除成功。



return 0;
}

stud *creat(int n)
{
int i;
stud *p, *h, *s; // *h保存表头结点的指针,*p指向当前结点的前一个结点,*s指向当前结点
    h = (stud *)malloc(sizeof (stud));
if ( h == NULL)  //检测
{
printf ("分配失败!\n");
exit (0);
}
h->name[20] = '\0'; //把表头结点的数据域置空
h->number = NULL;
h->link = NULL; //把表头结点的链域置空
p = h;       /*p指向表头结点*/
for (i=0; i<n; i++)
{
s = (stud *)malloc(sizeof (stud));
if  (s == NULL)
{
printf ("分配失败!\n");
exit (0);
}
printf("请输入第%d个人的学号:", i+1);
        scanf ("%d", &s->number);
getchar (); //读取回车 以免造成影响。
printf("请输入第%d个人的姓名:", i+1);
scanf ("%s",s->name);
getchar ();//读取回车 以免造成影响。
s->link = NULL;  //把当前链 链域 赋空值。
p->link = s; //把新建的链地址付给上一个链的节点, 以便连接上一个链和当前链;
p = s;
}
return h;   //返回链表头位置,方便对链表操作

}

stud * search(stud *h)
{

stud *p;     // 当前指针地址
char *y, x[20];    // 保存节点内数据域内姓名指针

printf ("请输入您所要查找的人的姓名:");
gets (x);

p = h->link;
while (p != NULL)
{
y = p->name;
if (strcmp (y, x) == 0)
{
printf ("您要查找的学生如下\n学号为:%d\n姓名为:%s\n",p->number, p->name);
return p;
}
else
p = p->link;
}
if (p == NULL)  // 这个if要不要都无所谓,只要跳出循环 应该就等于NULL了
{
printf ("信息系统中没有您所要查找的信息! \n");



}


void * insert(stud *p) //p是表头,直接插入后面,然后进行排序。
{
stud *s;
s = (stud *)malloc (sizeof(stud));
if (s == NULL)
{
printf ("插入位置分配失败!\n");
exit (0);
}
printf ("请输入您要插入学生的学号:");
scanf ("%d", &s->number);
getchar ();
printf ("请输入您要插入学生的姓名:");
scanf ("%s", s->name);
getchar ();
s->link = p->link;
p->link = s;
}

void del(stud *h)
{
stud *p,*s,*m; //p是待删除的,s是上一个,m是下一个。
int a,b;
printf ("请输入要删除的学生学号:");
scanf ("%d", &a);
p = h->link;
s = h;
m = p->link;
while (p != NULL)
{
if (a == p->number)
{
s->link = m->link;
printf ("删除成功!\n");
}
p = p->link;
s = p;
m = p->link;
}
}



除了删除函数del 其他函数都经过测试没有问题。
 删除函数哪儿出问题了???   很奇怪啊?  程序运行后 显示删除成功 然后直接说内存出错!上图

一个关于链表操作的有关问题。程序运行出错 求大神解答啊
明天回来继续调试!  请大家为小菜解答一下啊!!!
万分感谢!!
------解决思路----------------------
试试这个:
void del(stud *h)
{
    stud *p,*s,*m; //p是待删除的,s是上一个,m是下一个。
    int a,b;
    printf ("请输入要删除的学生学号:");
    scanf ("%d", &a);
    p = h->link;
    s = h;
    m = p->link;
    while (p != NULL)
    {
        if (a == p->number)
        {
            s->link = m->link;
            printf ("删除成功!\n");
            return;   //删除成功就结束函数,不要执行后面的指针赋值语句
        }
        p = p->link;
        s = p;
        m = p->link;
    }
}

------解决思路----------------------
引用:
试试这个:
void del(stud *h)
{
    stud *p,*s,*m; //p是待删除的,s是上一个,m是下一个。
    int a,b;
    printf ("请输入要删除的学生学号:");
    scanf ("%d", &a);
    p = h->link;
    s = h;
    m = p->link;
    while (p != NULL)
    {
        if (a == p->number)
        {
            s->link = m->link;
            printf ("删除成功!\n");
            free( p ); //释放空间
            return;   //删除成功就结束函数,不要执行后面的指针赋值语句
        }
        p = p->link;
        s = p;
        m = p->link;
    }
}


            free( p ); //释放空间
            return;   //删除成功就结束函数,不要执行后面的指针赋值语句
------解决思路----------------------
 m = p->link;
改成
if ( p!=NULL )  m = p->link;
------解决思路----------------------

void del(stud *h)
{
    stud *p,*s,*m; //p是待删除的,s是上一个,m是下一个。
    int a,b;
    printf ("请输入要删除的学生学号:");
    scanf ("%d", &a);
    p = h->link;
    s = h;
    m = p->link;
    while (p != NULL)
    {
        if (a == p->number)
        {
            s->link = m;  //注意位置
            printf ("删除成功!\n");
           break;
        }
        s = p;             //注意顺序!
        p = p->link;

        m = p->link;
    }
}