关于#函数返回#的问题,如何解决?

#include 
#include 
#include 
typedef struct DNode{
    int data;//值域
    struct DNode * prior;//前驱指针
    struct DNode * next;//后继指针
}DLinkNode;
void createListF(DLinkNode * L ,int a[],int n);//创建双链表,采用头插法(与a数组元素顺序相反)
void createListR(DLinkNode *L,int a[],int n);//采用尾插法创建双链表
void traverse_list(DLinkNode* pHead);
void destroy_list(DLinkNode* pHead);
int main(){
    int a[3] = {1,2,3};
    DLinkNode *L = NULL;
    createListR(L,a,3);
    traverse_list(L);
    destroy_list(L);
    return 0;
}
void createListF(DLinkNode * L ,int a[],int n){
    L = (DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
    L->next = L->prior = NULL;
    for(int i = 0;i < n;i++)
    {
        DLinkNode * s = (DLinkNode*)malloc(sizeof(DLinkNode));
        s->data = a[i];
        s->next = L->next;//将新结点插入到头结点之后
        if(L->next != NULL)//L存在结点,修改前驱指针
            L->next->prior = s;
        L->next = s;
        s->prior = L;
       
    }
}
void traverse_list(DLinkNode* pHead)
{
   DLinkNode *  t = pHead->next; // t指向首结点

    while (t != NULL)
    {
        printf("%d ", t->data);
        t = t->next;
    }
    printf("\n");
    return;
}
void destroy_list(DLinkNode* pHead){
    DLinkNode* pre = pHead,*p = pHead->next;
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);//循环结束时,p为NULL,pre指向尾结点,释放尾结点
}
void createListR(DLinkNode *L,int a[],int n){
    L = (DLinkNode *)malloc(sizeof(DLinkNode));
    L->prior = NULL;
    DLinkNode * r =L;
    for(int i = 0 ;i < n; i++){
        DLinkNode * s = (DLinkNode *)malloc(sizeof(DLinkNode));
        s->data = a[i];
        r->next = s;
        s->prior = r;
        r = s;
    }
    r->next = NULL;
    return;
}

上面代码,函数crateListR()无返回值,调用遍历函数traverse_list(),并不会打印结点。

#include 
#include 
#include 
typedef struct DNode{
    int data;//值域
    struct DNode * prior;//前驱指针
    struct DNode * next;//后继指针
}DLinkNode;
DLinkNode* createListF(DLinkNode * L ,int a[],int n);//创建双链表,采用头插法
DLinkNode* createListR(DLinkNode *L,int a[],int n);//采用尾插法创建双链表
void traverse_list(DLinkNode* pHead);
void destroy_list(DLinkNode* pHead);
int main(){
    int a[5] = {1,2,3,8,9};
    DLinkNode *L = NULL;
    L = createListF(L,a,5);
    traverse_list(L);
    destroy_list(L);
    return 0;
}
DLinkNode* createListF(DLinkNode * L ,int a[],int n){
    L = (DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
    L->next = L->prior = NULL;
    for(int i = 0;i < n;i++)
    {
        DLinkNode * s = (DLinkNode*)malloc(sizeof(DLinkNode));
        s->data = a[i];
        s->next = L->next;//将新结点插入到头结点之后
        if(L->next != NULL)//L存在结点,修改前驱指针
            L->next->prior = s;
        L->next = s;
        s->prior = L;
       
    }
    return L;
}
void traverse_list(DLinkNode* pHead)
{
   DLinkNode *  t = pHead->next; // t指向首结点

    while (t != NULL)
    {
        printf("%d ", t->data);
        t = t->next;
    }
    printf("\n");
    return;
}
void destroy_list(DLinkNode* pHead){
    DLinkNode* pre = pHead;
    DLinkNode* p = pHead->next;
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);//循环结束时,p为NULL,pre指向尾结点,释放尾结点
}
DLinkNode* createListR(DLinkNode *L,int a[],int n){
    L = (DLinkNode *)malloc(sizeof(DLinkNode));
    L->prior = NULL;
    DLinkNode * r =L;
    for(int i = 0 ;i < n; i++){
        DLinkNode * s = (DLinkNode *)malloc(sizeof(DLinkNode));
        s->data = a[i];
        r->next = s;
        s->prior = r;
        r = s;
    }
    r->next = NULL;
    return L;
}

把函数crateListR()返回改为返回DLinkNode*后(并赋给L),调用遍历函数traverse_list(),才能打印出结点。
实参L传给形参L,函数调用后形参L会被释放,但malloc()开辟的内存空间在函数调用后并不会被释放,为什么会出现这种情况呢?

第一段里,void createListF(DLinkNode * L ,int a[],int n)函数,在主函数调用时,形参DLinkNode * L只是完成了值传递,在函数里对形参*L操作,仅限在函数体内,并不能影响到主函数里的实参L。
第二段里,虽然DLinkNode* createListF(DLinkNode * L ,int a[],int n)函数,形参DLinkNode * L只是完成了值传递,在函数里对形参*L操作,仅限在函数体内,但函数是有返回值的,通过函数的返回值将在函数体内对形参*L的操作改变等返回到主函数并赋值给主函数里的实参L,即 L = createListF(L,a,5);达到改变主函数里实参L的目的。