Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C、 逐个元素的空闲子列表会导致意外行为_C_Free - Fatal编程技术网

C、 逐个元素的空闲子列表会导致意外行为

C、 逐个元素的空闲子列表会导致意外行为,c,free,C,Free,我在另一个链表中有一个链表,typedef如下所示: typedef struct struct_execution_queue { list_run_str *runstr; list_run_str *marker; //just a pointer to a specific element in runstr (it was not allocated with `malloc()`) int excount; struct struct_execu

我在另一个链表中有一个链表,typedef如下所示:

typedef struct struct_execution_queue {

    list_run_str *runstr;
    list_run_str *marker; //just a pointer to a specific element in runstr (it was not allocated with `malloc()`)

    int excount;

    struct struct_execution_queue *next;
}list_ex;
list\u run\u str
是另一个链接列表:

typedef struct struct_run_str { //run element
    char car;
    struct struct_run_str *next;
    struct struct_run_str *prev;
} list_run_str;
我实现了一个
insert()。我尝试运行一个简单的测试代码,看看内存管理是否正常:

int main(){
/*read data from input file and insert into lists (this part is ok)
I have all data I need: two rheads and two markers
*/
list_ex *exhead = NULL;

exhead = insert(exhead, rheadone, markerone, 10);
exhead = insert(exhead, rheadtwo, markertwo, 20);

free_ex_list(exhead);

}
要释放所有
exhead
元素,我需要首先释放相对子列表。 由于
rhead
exhead
的子列表)也是一个链表(分配有
malloc()
),我认为应该逐个元素释放它。这是我使用的代码:

void free_run_str_list(list_run_str *head) { //free a list_run_str list
    list_run_str *tmp;

    while (head != NULL) {
        tmp = head;
        head = head->next;
        free(tmp);
    } // <--------------------- breackpoint triggered here
}

void free_ex_list(list_ex *head) { //free a list_ex list
    list_ex *tmp;

    while (head != NULL) {
        tmp = head;
        free_run_str_list(tmp->runstr);
        head = head->next;
        free(tmp);
    }
}
谢谢你的帮助

编辑

下面是导致问题的确切代码,我尽量简化它

代码:

#包括
#包括
#包括
类型定义结构结构运行结构{
炭车;
struct struct_run_str*next;
struct struct_run_str*prev;
}列出"跑步"路线;;
类型定义结构执行队列{
list_run_str*runstr;//这将与malloc()一起分配
list_run_str*marker;//这只是指向runstr中某个元素的指针
国际汇算;
结构执行队列*下一步;
}列表(例如);;
作废自由运行列表(列表运行列表*头){//释放“列表运行列表”列表
列出_run _str*tmp;
while(head!=NULL){
tmp=头部;
头部=头部->下一步;
免费(tmp);
}
}
作废自由列表(列表头){//释放“列表头”列表
列表_ex*tmp;
while(head!=NULL){
tmp=头部;
自由运行列表(tmp->runstr);
头部=头部->下一步;
免费(tmp);
}
}
list_run_str*loadrunstr(list_run_str*head,char c){//在“list_run_str”列表的ed处添加一项
列出运行模式*tmp、*tmphead;
if((tmp=(list\u run\u str*)malloc(sizeof(list\u run\u str))){
tmp->car=c;
tmp->next=NULL;
if(head==NULL){
tmp->prev=NULL;
水头=tmp;
}
否则{
for(tmphead=head;tmphead->next!=NULL;tmphead=tmphead->next);
tmphead->next=tmp;
tmp->prev=tmphead;
}
}
其他的
printf(“loadrunstr mem error\n”);
回流头;
}
list_run_str*复制(list_run_str*头,list_run_str*标记,list_run_str**新标记){//将复制头换成新标记并调整新标记
列出新头、新头、tmphead;
内特马克波斯,莱恩,i;
//查找列表长度
for(len=0,tmphead=head;tmphead!=NULL;len++,tmphead=tmphead->next);
//查找标记位置
markerpos=0;
如果(标记!=NULL)
for(tmphead=marker;tmphead->prev!=NULL;markerpos++,tmphead=tmphead->prev);
//创建新的“列表\u运行\u str”列表
如果((newhead=(list\u run\u str*)malloc(sizeof(list\u run\u str)*len))){
i=0;
//加载头部
newtmhead=newhead;
tmphead=头部;
(newtmphead+i)->prev=NULL;
(newtmhead+i)->next=(newtmhead+i+1);
(newtmhead+i)->car=tmphead->car;
//加载其他元素
对于(i++,tmphead=tmphead->next;tmphead!=NULL;i++,tmphead=tmphead->next){
(newtmhead+i)->car=tmphead->car;
(newtmhead+i)->next=(newtmhead+i+1);
(newtmhead+i)->prev=(newtmhead+i-1);
}
((newtmphead)+len-1)->next=NULL;
//更新新标记位置
对于(i=0,newtmhead=newhead;inext);
*newmarker=newtmhead;
}
其他的
printf(“重复的内存错误\n”);
返回newhead;
}
list_ex*insert(list_ex*exhead,list_run_str*rhead,list_run_str*marker,int count){//在“list_ex”列表的头部插入新元素
列表_ex*tmp;
列表\u run\u str*tmphead,*tmpmarker;
if((tmp=(list_ex*)malloc(sizeof(list_ex))){
tmphead=重复(rhead、标记器和TMP标记器);
tmp->runstr=tmphead;
tmp->marker=tmpmarker;
tmp->excount=计数;
tmp->next=挖掘;
挖掘=tmp;
}
其他的
printf(“插入内存错误\n”);
返回tmp;
}
int main(){
列明(例如)劝谕;;
列出rheadone、*markerone、*rheadtwo、*markertwo;
告诫=无效;
rheadone=NULL;
rheadtwo=NULL;
//在rheadone中加载一些项目
rheadone=loadrunstr(rheadone,'a');
rheadone=loadrunstr(rheadone,'b');
rheadone=loadrunstr(rheadone,'c');
//在rheadtwo中加载一些项目
rheadtwo=loadrunstr(rheadtwo,'d');
rheadtwo=loadrunstr(rheadtwo,'e');
rheadtwo=loadrunstr(rheadtwo,'f');
//将markerone设置为指向rheadone中的某个字符
markerone=rheadone->next;//指向“b”
//将markertwho设置为指向rheadtwo中的某个字符
markertwo=rheadtow2;//指向“d”
//在摘要中插入两个新元素
启封=插入(启封,雷亚东,马克罗恩,10);
exhead=插入(exhead,rheadone,markerone,20);
//试着释放他们
免费除名名单(摘要);
返回0;
}

从您发布的代码中,问题出在函数
复制中。它将变量
len
设置为要复制的列表的长度,并调用
malloc
来分配
list\u run\u str
len
元素块。然后,它填充这些元素并将它们连接到一个链表中,链表包含
list\u run\u str
,执行其他操作并返回指向第一个元素的指针

据推测,函数
duplicate
的返回值会在
列表的
runstr
成员中结束

free\u list\u ex
调用的
free\u run\u str\u list
函数对链接列表的每个项目调用
free
。如果此链表是由函数
duplicate
构建的,则对
free
的第一次调用将释放整个块。然而,
list_ex *insert(list_ex *exhead, list_run_str *rhead, list_run_str *marker, int count) {
    list_ex *tmp;
    list_run_str *tmphead, *tmpmarker;

    if ((tmp = (list_ex *)malloc(sizeof(list_ex)))) {

        tmphead = duplicate(rhead, marker, &tmpmarker);
        tmp->runstr = tmphead;
        tmp->marker = tmpmarker;

        tmp->excount = count;

        tmp->next = exhead;
        exhead = tmp;
    }
    else
        printf("insert mem error\n");
    return tmp;
}



list_run_str *duplicate(list_run_str *head, list_run_str *marker, list_run_str **newmarker) { //duplicate a list_run_str_list and the relative marker
    list_run_str *newhead, *newtmphead, *tmphead;
    int markerpos, len, i;

    //find list length
    for (len = 0, tmphead = head; tmphead != NULL; len++, tmphead = tmphead->next);

    //find marker position in head
    markerpos = 0;
    if (marker != NULL)
        for (tmphead = marker; tmphead->prev != NULL; markerpos++, tmphead = tmphead->prev);

    //create new list_run_str list
    if ((newhead = (list_run_str *)malloc(sizeof(list_run_str) * len))) {
        i = 0;
        //load the new head
        newtmphead = newhead;
        tmphead = head;

        (newtmphead + i)->prev = NULL;
        (newtmphead + i)->next = (newtmphead + i + 1);
        (newtmphead + i)->car = tmphead->car;

        //load other elements
        for (i++, tmphead = tmphead->next; tmphead != NULL; i++, tmphead = tmphead->next) {
            (newtmphead + i)->car = tmphead->car;
            (newtmphead + i)->next = (newtmphead + i + 1);
            (newtmphead + i)->prev = (newtmphead + i - 1);
        }
        ((newtmphead)+len - 1)->next = NULL;

        //update the new marker
        for (i = 0, newtmphead = newhead; i < markerpos; i++, newtmphead = newtmphead->next);
        *newmarker = newtmphead;
    }
    else
        printf("duplicate mem error\n");
    return newhead;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct struct_run_str {
    char car;
    struct struct_run_str *next;
    struct struct_run_str *prev;
} list_run_str;

typedef struct struct_execution_queue {
    list_run_str *runstr; //this will be allocated with malloc()
    list_run_str *marker; //this is only a pointer to a certain element in runstr

    int excount;

    struct struct_execution_queue *next;
}list_ex;

void free_run_str_list(list_run_str *head) { //free a "list_run_str" list
    list_run_str *tmp;

    while (head != NULL) {
        tmp = head;
        head = head->next;
        free(tmp);
    }
}

void free_ex_list(list_ex *head) { //free a "list_ex" list
    list_ex *tmp;

    while (head != NULL) {
        tmp = head;
        free_run_str_list(tmp->runstr);
        head = head->next;
        free(tmp);
    }
}

list_run_str *loadrunstr(list_run_str *head, char c) { //add an item at the ed of a "list_run_str" list
    list_run_str *tmp, *tmphead;

    if ((tmp = (list_run_str *)malloc(sizeof(list_run_str)))) {
        tmp->car = c;
        tmp->next = NULL;

        if (head == NULL) {
            tmp->prev = NULL;
            head = tmp;
        }
        else {
            for (tmphead = head; tmphead->next != NULL; tmphead = tmphead->next);
            tmphead->next = tmp;
            tmp->prev = tmphead;
        }
    }
    else
        printf("loadrunstr mem error\n");
    return head;
}

list_run_str *duplicate(list_run_str *head, list_run_str *marker, list_run_str **newmarker) { //duplicte head to newhed and adjust newmarker
    list_run_str *newhead, *newtmphead, *tmphead;
    int markerpos, len, i;

    //find list length
    for (len = 0, tmphead = head; tmphead != NULL; len++, tmphead = tmphead->next);

    //find marker position
    markerpos = 0;
    if (marker != NULL)
        for (tmphead = marker; tmphead->prev != NULL; markerpos++, tmphead = tmphead->prev);

    //create new "list_run_str" list
    if ((newhead = (list_run_str *)malloc(sizeof(list_run_str) * len))) {
        i = 0;
        //load the head
        newtmphead = newhead;
        tmphead = head;

        (newtmphead + i)->prev = NULL;
        (newtmphead + i)->next = (newtmphead + i + 1);
        (newtmphead + i)->car = tmphead->car;

        //load the other elements
        for (i++, tmphead = tmphead->next; tmphead != NULL; i++, tmphead = tmphead->next) {
            (newtmphead + i)->car = tmphead->car;
            (newtmphead + i)->next = (newtmphead + i + 1);
            (newtmphead + i)->prev = (newtmphead + i - 1);
        }
        ((newtmphead)+len - 1)->next = NULL;

        //update new marker position
        for (i = 0, newtmphead = newhead; i < markerpos; i++, newtmphead = newtmphead->next);
        *newmarker = newtmphead;
    }
    else
        printf("duplicate mem error\n");
    return newhead;
}

list_ex *insert(list_ex *exhead, list_run_str *rhead, list_run_str *marker, int count) { //insert new element in the head of a "list_ex" list
    list_ex *tmp;
    list_run_str *tmphead, *tmpmarker;

    if ((tmp = (list_ex *)malloc(sizeof(list_ex)))) {

        tmphead = duplicate(rhead, marker, &tmpmarker);
        tmp->runstr = tmphead;
        tmp->marker = tmpmarker;

        tmp->excount = count;

        tmp->next = exhead;
        exhead = tmp;
    }
    else
        printf("insert mem error\n");
    return tmp;
}

int main() {
    list_ex *exhead;
    list_run_str *rheadone, *markerone, *rheadtwo, *markertwo;

    exhead = NULL;
    rheadone = NULL;
    rheadtwo = NULL;

    //load some items in rheadone
    rheadone = loadrunstr(rheadone, 'a');
    rheadone = loadrunstr(rheadone, 'b');
    rheadone = loadrunstr(rheadone, 'c');

    //load some items in rheadtwo
    rheadtwo = loadrunstr(rheadtwo, 'd');
    rheadtwo = loadrunstr(rheadtwo, 'e');
    rheadtwo = loadrunstr(rheadtwo, 'f');

    //set markerone to point at some char in rheadone
    markerone = rheadone->next; //points to 'b'

    //set markertwho to point at some char in rheadtwo
    markertwo = rheadtwo; //points to 'd'

    //insert two new elements into exhead
    exhead = insert(exhead, rheadone, markerone, 10);
    exhead = insert(exhead, rheadone, markerone, 20);

    //try to free them
    free_ex_list(exhead);

    return 0;
}