首页 > 解决方案 > C :: 内存访问冲突随机出现在链表中

问题描述

所以这是让我头疼的代码:

void newCopy(ListNode* n, List* l) {
    if (n == NULL) { return; }

    if (n->next == NULL) {
        push(n->data, l);
        return;
    }
    else {
        newCopy(n->next, l);
        push(n->data, l);
        return;
    }
}

如您所见,如果 n == NULL 则该函数应该结束,但您看到它即将到来:它并没有结束该函数。

if (n->next == NULL)由于 n 为 NULL ,我得到“读取访问冲突” 。我在其他功能上也随机出现错误,所有这些都与内存访问有关。您应该研究的功能是State* progDynState(List* taskList)因为一切都在这里完成。

我知道有些人想要最小的可复制示例,我无法制作一个,因为所有内容都已使用,所以这里是整个代码。

文件主要:

#include "Tools.h"
#include <time.h> 

int main()
{
    /* initialize random seed: */
    srand(time(NULL));

    //List creation
    //
    List* taskList = consList();
    Task* task = NULL;
    //Task number
    /*int n = (rand() % 14 + 4);
    //Generate random tasks
    for(int i = 1; i <= n; i++) {
        task = consTask(i + (rand() % 10 + 1) - rand() % 5 , i + (rand() % 10 + 1) - rand() % 5);
        push(task, taskList);
    }*/
    
    for (int i = 1; i <= 4; i++) {
        task = consTask(i,i);
        push(task, taskList);
    }

    std::cout << "Display origin : \n" << listToString_Task(taskList) << " \n";

    //--- CLASSIC ---
    //SOLVE PROBLEM - PROG DYN STATE
    State* opt = progDynState(taskList);


    //--- FPTAS ---
    double sigma = 1; //TO CHANGE DEPENDING ON PRECISION
    //Get deltas 
    double deltaD = findDeltaD(taskList, sigma);
    double deltaL = findDeltaL(taskList, sigma);
    //Rounded values
    List* rL = rounding(taskList, deltaD, deltaL);
    //SOLVE PROBLEM - PROG DYN STATE
    std::cout << "ROUNDED OPT : \n";
    State* roundedOpt = progDynState(rL);
    //Transpose the solution on the original instance
    List* pair = createListTaskPair(taskList, rL);
    State* FPTASopt = transpose(roundedOpt, pair);
    std::cout << "Optimal Solution 2 : \n" << stateToString(FPTASopt) << " \n";
}

文件问题元素.h

#pragma once
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#include <algorithm> 

#ifndef PROBLEM
#define PROBLEM

// -----------------------------------------------------//
// ------------------ LIST ------------------//
// -----------------------------------------------------//

typedef struct ListNode ListNode;
struct ListNode
{
    void *data;
    struct ListNode *next;
};

typedef struct List List;
struct List
{
    struct ListNode *head;
    struct ListNode *tail;
    int size;
};

//Initialize a list's value
void empty(List* l);

//Create an empty list
List* consList()    //allocate and initialize to NULL values
{
    List* list = (List*)calloc(1,sizeof(List*));
    while(list == NULL) list = (List*)calloc(1,sizeof(List*));
    empty(list);
    return list;
}

//Add data to the head of the list
void push(void *data, List *list)
{
    if (list == NULL) return;
    if (data == NULL) return;
    ListNode *newNode = (ListNode*)calloc(1,sizeof(ListNode));
    newNode->data = data;
    newNode->next = list->head;
    if (list->head == NULL)    //the list is empty
    {
        list->head = newNode;
        list->tail = list->head;
    }
    else
    {
        list->head = newNode;
    }
    list->size++;
}

//Add data to the tail of the list
void append(void *data, List *list)
{
    if (list == NULL) return;
    if (data == NULL) return;
    ListNode *newNode = (ListNode*)calloc(1,sizeof(ListNode));
    newNode->data = data;
    newNode->next = NULL;
    if (list->head == NULL)    //the list is empty
    {
        list->head = newNode;
        list->tail = list->head;
    }
    else
    {
        list->tail->next = newNode;
        list->tail = newNode;
    }
    list->size++;
}

//Remove first element
void pop(List* l) {
    if (l == NULL) return;
    if (l->head->next == NULL) {
        free(l->head);
        empty(l);
    }
    else {
        ListNode* ln = l->head;
        l->head = ln->next;
        free(ln);
    }
    l->size--;
}

void endPop(List* l) {
    if (l == NULL) return;
    if (l->head->next == NULL) {
        pop(l);
    }
    else {
        ListNode* curr = l->head;
        ListNode* prev = NULL;
        while (curr != l->tail) {
            prev = curr;
            curr = curr->next;
        }
        free(l->tail);
        prev->next = NULL;
        l->size--;
    }
}

//Remove element contening data
void removeData(void *data, List *list){
    if (data == NULL) return;
    if (list == NULL) return;
    if (list->head == NULL) return;

    //Head to be removed
    if (data == list->head->data) {
        pop(list); 
        return;
    } 
    //Tail to be removed
    if (data == list->tail->data){
        endPop(list);
        return;
    }
    //Other node
    ListNode* curr = list->head;
    ListNode* prev = NULL;
    while (curr->data != data) {
        prev = curr;
        curr = curr->next;
    }
    prev->next = curr->next;
    free(curr);
    list->size--;
}

//Make l1's head and tail point to l2's
void assignTo(List* l1, List* l2) {
    if (l1 == NULL) return;
    if (l2 == NULL) return;
    l1->head = l2->head;
    l1->tail = l2->tail;
    l1->size = l2->size;
}

//Initialize a list's value
void empty(List* l) {
    if (l == NULL) return;
    l->head = NULL;
    l->tail = NULL;
    l->size = 0;
}

//Free memory of all nodes
void freeNodes(List* l) {
    if (l == NULL) return;
    if (l->head->next == NULL) {
        pop(l);
        return;
    }
    while (l->head != NULL) {
        pop(l);
    }
}

//Create a copy of n in l with new elements, shared data pointer
void newCopy(ListNode* n, List* l) {
    if (n == NULL) { return; }

    if (n->next == NULL) {
        push(n->data, l);
        return;
    }
    else {
        newCopy(n->next, l);
        push(n->data, l);
        return;
    }
}


// -----------------------------------------------------//
// ------------------ STATE ------------------//
// -----------------------------------------------------//

typedef struct State State;
struct State
{
    double _eOe; //End of execution
    double _t; //Start of next task on first machine
    //First machine
    List* _task1;
    //Second machine
    List* _task2;
};

//Constructor of State
State* consState(double eOe = 0, double t = 0) {
    State* s = (State*)malloc(sizeof(State));
    s->_t = t;
    s->_eOe = eOe;
    s->_task1 = consList();
    s->_task2 = consList();
    return s;
}

//Describe a list of task
std::string listToString_Task(List* tL);

//Describe a state
std::string stateToString(struct State * s) {
    std::string st;
    st += "State : ( t =  " + std::to_string(s->_t) + " , eOe = " + std::to_string(s->_eOe) + " ) \n";
    st += "Task on machine 1 : (" + listToString_Task(s->_task1) + ") \n";
    st += "Task on machine 2 : (" + listToString_Task(s->_task2) + ") \n";
    st += "End of execution : " + std::to_string(s->_eOe);
    return st;
}


// -----------------------------------------------------//
// ------------------ TASK ------------------//
// -----------------------------------------------------//

typedef struct Task Task;
struct Task
{
    double _dur;//task duration
    double _lat;//task latency
};

//Constructor of Task
Task* consTask(double dur = 0, double lat = 0) {
    Task* t = (Task*)malloc(sizeof(Task));
    t->_dur = dur;
    t->_lat = lat;
    return t;
}

//Describe a task
std::string taskToString(struct Task * t) {
    return "Task : ( _dur =  " + std::to_string(t->_dur) + " , _lat = " + std::to_string(t->_lat) + " )";
}


// -----------------------------------------------------//
// ------------------ PAIR : TASK | ROUNDED TASK   ------------------//
// -----------------------------------------------------//

typedef struct TaskPair TaskPair;
struct TaskPair
{
    Task* _origin;//original Tasks
    Task* _rounded;//rounded Tasks
};

//Constructor of TaskPair
TaskPair* consTaskPair(Task* origin, Task* rounded) {
    TaskPair* t = (TaskPair*)malloc(sizeof(TaskPair));
    t->_origin = origin;
    t->_rounded = rounded;
    return t;
}

//Describe a task
std::string taskPairToString(struct TaskPair * t) {
    return "TaskPair : ( origin =  " + taskToString(t->_origin) + " , rounded = " + taskToString(t->_rounded) + " )";
}

#endif // !PROBLEM

文件工具.h

#pragma once
#include "ProblemElements.h"

#ifndef TOOLS
#define TOOLS

// -----------------------------------------------------//
// ------------------ GENERAL TOOLS ------------------//
// -----------------------------------------------------//

std::string listToString_State(List* sL);
//Keeps only the best state of a PElement<State>.
List* keepBestState(List* sL) {
    if (sL == NULL) return NULL;
    if (sL->head->next == NULL) return sL;
    
    std::cout << "Size : " << std::to_string(sL->size) << "\n";
    std::cout << "sL : " << listToString_State(sL) << "\n";
    State* currS = (State*)sL->head->data;
    State* nextS = (State*)sL->head->next->data;
    //Current element is better, removing following element | Following element is better, removing current element
    if(currS->_eOe <= nextS->_eOe)
        removeData(sL->head->next->data, sL);
    else
        pop(sL);

    return keepBestState(sL);
}

//Split List in two half
void splitList(List* sL, List* half2) {
    //Size of list to sort
    int listSize = sL->size;

    //Half of size list
    if (listSize % 2 == 0) { 
        listSize = listSize / 2;
        sL->size = listSize;
        half2->size = listSize;
    }
    else {
        listSize = (listSize + 1) / 2;
        sL->size = listSize;
        half2->size = listSize-1;
    }

    ListNode* front = sL->head;

    for (int i = 1; i < listSize; i++) 
        front = front->next;

    //Start 2 half
    half2->head = front->next;
    //Cut main list
    front->next = NULL;
    //Set tails
    half2->tail = sL->tail;
    sL->tail = front;
}

//Merge two list of States sorted in increasing order into one list which is in increasing order || Comparing _t value
ListNode* sortedMerge_State(ListNode* a, ListNode* b)
{
    ListNode* result = NULL;

    //BASE CASE
    if (a == NULL)
        return(b);
    if (b == NULL)
        return(a);

    State* state1 = (State*)a->data;
    State* state2 = (State*)b->data;

    //Sort current value
    if (state1->_t <= state2->_t)
    {
        result = a;
        result->next = sortedMerge_State(a->next, b);
    }
    else
    {
        result = b;
        result->next = sortedMerge_State(a, b->next);
    }
    return result;
}//Merge two list of States sorted in increasing order into one list which is in increasing order

//Merge two list of Tasks sorted in decreasing order into one list which is in decreasing order || Comparing _lat value
ListNode* sortedMerge_Task(ListNode* a, ListNode* b)
{
    ListNode* result = NULL;

    if (a == NULL)
        return(b);
    if (b == NULL)
        return(a);

    Task* task1 = (Task*)a->data;
    Task* task2 = (Task*)b->data;

    if (task1->_lat >= task2->_lat)
    {
        result = a;
        result->next = sortedMerge_Task(a->next, b);
    }
    else
    {
        result = b;
        result->next = sortedMerge_Task(a, b->next);
    }
    return result;
}

//Sort a list of States by increasing order || Comparing _t value
void fusionSort_State(List* sL) {
    ListNode* head = sL->head;
    List* half2 = consList();

    if (head == NULL || head->next == NULL) return;
    //Cut list in two half
    splitList(sL, half2);

    //Recursiv call || Sort the two half
    fusionSort_State(sL);
    fusionSort_State(half2);

    //Merge and sort the sorted halfs
    sL->head = sortedMerge_State(sL->head,half2->head);
    sL->size = sL->size + half2->size;
    for (head = sL->head; head->next != NULL; head = head->next);
    sL->tail = head;
}

//Sort a list of Tasks by decreasing order || Comparing _lat value
void fusionSort_Task(List* sL) {
    ListNode* head = sL->head;
    List* half2 = consList();

    if (head == NULL || head->next == NULL) return;
    splitList(sL, half2);

    fusionSort_Task(sL);
    fusionSort_Task(half2);

    sL->head = sortedMerge_Task(sL->head,half2->head);
    sL->size = sL->size + half2->size;
    for (head = sL->head; head->next != NULL; head = head->next);
    sL->tail = head;
}

//Removes multiple occurence t
List* removeMultOcc(List* sL) {
    if (sL == NULL) return NULL;
    if (sL->head == NULL) return NULL;
    if (sL->size == 1) return sL;

    fusionSort_State(sL);
    ListNode* curr = sL->head;
    State* state1 = NULL;
    State* state2 = NULL;

    //SIMILAR t
    while (curr != NULL && curr->next != NULL) {
        state1 = (State*)curr->data;
        state2 = (State*)curr->next->data;
        //Current and following element considered as duplicate
        if (state1->_t == state2->_t) {
            //Remove bad duplicate
            if (state1->_eOe <= state2->_eOe)
                removeData(state2, sL);
            else
                removeData(state1, sL);
        }
        //Next duplicate group
        else curr = curr->next;
    }
    return sL;
}

//Summ of _dur
double sumDurTaskList(ListNode* tL) {
    if (tL == NULL) return NULL;
    Task* task = (Task*)tL->data;
    if (tL->next == NULL) return task->_dur;

    return task->_dur + sumDurTaskList(tL->next);
}

//Describe a list of state
std::string listToString_State(List* sL) {
    if (sL == NULL) return "List : [ NOT INITIALIZED ].\n";
    if (sL->size == 0) return "List : [ EMPTY ].\n";
    if (sL->size == 1) return "START OF LIST OF STATE : [ " + stateToString((State*)sL->head->data) + " ]. END OF LIST OF STATE\n";

    ListNode* curr = sL->head;
    std::string st = "START OF LIST OF STATE : [\n ";


    while (curr != NULL) {
        st += stateToString((State*)curr->data);

        if (curr->next != NULL) st += "\n \n";

        curr = curr->next;
    }

    return st + " \n]. END OF LIST OF STATE \n \n \n";
}

//Describe a list of task
std::string listToString_Task(List* tL) {
    if (tL == NULL) return "List : [ NOT INITIALIZED ].\n";
    if (tL->size == 0) return "List : [ EMPTY ].\n";
    if (tL->size == 1) return "START OF LIST OF TASK : [ " + taskToString((Task*)tL->head->data) + " ]. END OF LIST OF TASK\n";

    ListNode* curr = tL->head;
    std::string st = "START OF LIST OF TASK : [ \n";


    while (curr != NULL) {
        st += taskToString((Task*)curr->data);

        if (curr->next != NULL) st += "\n";

        curr = curr->next;
    }

    return st + "\n]. END OF LIST OF TASK\n \n \n";
}

//Describe a list of taskpair
std::string listToString_TaskPair(List* tL) {
    if (tL == NULL) return "List : [ NOT INITIALIZED ].\n";
    if (tL->size == 0) return "List : [ EMPTY ].\n";
    if (tL->size == 1) return "START OF LIST OF TASKPAIR : [ " + taskPairToString((TaskPair*)tL->head->data) + " ]. END OF LIST OF TASKPAIR\n";

    ListNode* curr = tL->head;
    std::string st = "START OF LIST OF TASKPAIR : [ \n";


    while (curr != NULL) {
        st += taskPairToString((TaskPair*)curr->data);

        if (curr->next != NULL) st += "\n";

        curr = curr->next;
    }

    return st + "\n]. END OF LIST OF TASKPAIR\n \n \n";
}


// -----------------------------------------------------//
// ------------------ FPTAS TOOLS ------------------//
// -----------------------------------------------------//

//All Task on machine 2, Tasks sorted by decreasing order of latency 
State* heuristic(List* l) {
    //Copy list to not modify original instance
    List* copyL = consList();
    newCopy(l->head, copyL);
    //Sort by decreasing order
    fusionSort_Task(copyL);

    ListNode* curr = copyL->head;
    Task* currT = (Task*)curr->data;
    //Heuristic's result
    State* H = consState();

    double temp_t = 0;
    double temp_q = 0;
    //Placed Task total duration
    double Ak = 0;

    //Heuristic
    while (curr != NULL) {
        temp_t = Ak / 2 + (currT->_dur / 2);
        temp_q = fmax(temp_t + currT->_lat, H->_eOe);
        H->_eOe = temp_q;
        append(currT, H->_task2);
        Ak += currT->_dur;
        curr = curr->next;
    }

    return H;
}

//Return the delta value for duration
double findDeltaD(List* l, double sigma) { return (sigma*sumDurTaskList(l->head)) / (4 * l->size); }

//Return the delta value for latency
double findDeltaL(List* l, double sigma) {
    List* copyL = consList();
    newCopy(l->head, copyL);
    return (sigma*heuristic(copyL)->_eOe) / (6 * l->size);
}

//Round duration depending on deltaD and latency depending on deltaL || Create a new list
List* rounding(List* taskList, double deltaD, double deltaL) {
    //Current node
    ListNode* curr = taskList->head;
    //Current task
    Task* currT = NULL;
    //Rounded task
    Task* newT = NULL;
    //Rounded task list
    List* l = consList();

    if (taskList->size == 1) {
        currT = (Task*)curr->data;
        newT = consTask(std::ceil(currT->_dur / deltaD) * deltaD, std::ceil(currT->_lat / deltaL) * deltaL);
        push(newT, l);
        return l;
    }

    while (curr != NULL) {
        currT = (Task*)curr->data;
        newT = consTask(std::ceil(currT->_dur / deltaD) * deltaD, std::ceil(currT->_lat / deltaL) * deltaL);
        append(newT, l);
        curr = curr->next;
    }

    return l;
}

//Create a new list pairing the corresponding original and rounded Tasks 
List* createListTaskPair(List* origin, List* rounded) {
    //Paired list
    List* pairL = consList();
    ListNode* currO = origin->head;
    ListNode* currR = rounded->head;
    TaskPair* pair = NULL;

    while (currO != NULL) {
        //Create pair
        pair = consTaskPair((Task*)currO->data, (Task*)currR->data);
        //Add pair
        append(pair, pairL);
        //Next value
        currO = currO->next;
        currR = currR->next;
    }

    return pairL;
}

//Transpose Optimal Solution of a rounded instance to it's original instance
State* transpose(State* opt, List* taskPair){
    //Transposed State || result
    State* trueOpt = consState();

    ListNode* currStateTask1 = opt->_task1->head;
    ListNode* currStateTask2 = opt->_task2->head;
    ListNode* currPair = taskPair->head;
    //Placed Task total duration
    double Ak = 0;

    //Transpose Machine 1 Task
    while (currStateTask1 != NULL) {
        //Current Task
        Task* currT = (Task*)currStateTask1->data;
        bool found = false;
        TaskPair* currP = NULL;

        //Search in Pairs
        while (!found) {
            currP = (TaskPair*)currPair->data;
            if (currT == currP->_rounded) found = true;
            else currPair = currPair->next;
        }

        //Add Task to transposed State
        append(currP->_origin, trueOpt->_task1);
        //Add Task duration to _t
        trueOpt->_t += currP->_origin->_dur;
        //Define new _eOe
        trueOpt->_eOe = fmax(trueOpt->_t + currP->_origin->_lat , trueOpt->_eOe);

        //Remove Task to speed up next research
        removeData(currP, taskPair);
        //Reinitialize to head
        currPair = taskPair->head;
        //Next Task to transpose
        currStateTask1 = currStateTask1->next;
    }
    
    //Only Machine 1 execution
    Ak = trueOpt->_t;

    //Transpose Machine 2 Task
    while (currStateTask2 != NULL) {
        //Current Task
        Task* currT = (Task*)currStateTask2->data;
        bool found = false;
        TaskPair* currP = NULL;

        //Search in Pairs
        while (!found) {
            currP = (TaskPair*)currPair->data;
            if (currT == currP->_rounded) found = true;
            else currPair = currPair->next;
        }

        //Add Task to transposed State
        append(currP->_origin, trueOpt->_task2);
        //Define new _eOe
        trueOpt->_eOe = fmax((Ak - trueOpt->_t)/2 + currP->_origin->_dur/2 + currP->_origin->_lat, trueOpt->_eOe);

        //Add curr Task time to Ak
        Ak += currP->_origin->_dur;
        //Remove Task to speed up next research
        removeData(currP, taskPair);
        //Reinitialize to head
        currPair = taskPair->head;
        //Next Task to transpose
        currStateTask2 = currStateTask2->next;
    }

    return trueOpt;
}


// -----------------------------------------------------//
// ------------------ PROG DYN ALGO ------------------//
// -----------------------------------------------------//

//Use Dynamic Programmation based on States to find an Optimal Solution
State* progDynState(List* taskList) {
    std::cout << "PROG DYN | State ==>> \n";
    std::cout << "Task List :: \n" << listToString_Task(taskList) << "\n";

    //Get-through list
    ListNode * currT = taskList->head;

    //Start state, (0 , 0 , 0 , 0)
    State* start = consState();
    //State list
    List* sL = consList(); //Xi-1
    push(start, sL);
    List* sL2 = consList();//Xi
    //Get through list
    ListNode* currS = sL->head;
    //Placed Task total duration
    double Ak = 0;

    while (currT != NULL) {
        Task* ctask = (Task*)currT->data;
        empty(sL2);

        //Create new States with new Task and old States
        while (currS != NULL) {
            State* cstate = (State*)currS->data;
            //std::cout << "MM |||| MM - Mother State : " << stateToString(cstate) << "\n\n";
            //ON MACHINE 1
            //new start, start of state + task duration
            double temp_t = cstate->_t + ctask->_dur;
            //max between (start of state + latency of task) and (end of original state) 
            double temp_q = fmax(temp_t + ctask->_lat, cstate->_eOe);
            State * s1 = consState(temp_q, temp_t);
            //Keep track of tasks on first machine
            newCopy(cstate->_task1->head, s1->_task1);
            append(currT->data, s1->_task1);
            //Keep track of tasks on second machine
            newCopy(cstate->_task2->head, s1->_task2);
            //std::cout << "S1 |||| S1 - State 1 : " << stateToString(s1) << "\n\n";
            //Add state to list
            push(s1, sL2);

            //ON MACHINE 2
            //new start, start of state + task duration
            temp_t = (Ak - cstate->_t) / 2 + (ctask->_dur / 2);
            //max between (start of state + latency of task) and (end of original state) 
            temp_q = fmax(temp_t + ctask->_lat, cstate->_eOe);
            State * s2 = consState(temp_q, cstate->_t);
            //Keep track of tasks on second machine
            newCopy(cstate->_task2->head, s2->_task2);
            append(currT->data, s2->_task2);
            //Keep track of tasks on first machine
            newCopy(cstate->_task1->head, s2->_task1);
            //std::cout << "S2 |||| S2 - State 2 : " << stateToString(s2) << "\n\n";
            //Add state to list
            push(s2, sL2);

            //Next list member
            currS = currS->next;
        }
        //Xi CREATED

        //ERASE OLD SET OF STATE --- Xi-1
        freeNodes(sL);
        //SET IT ANEW --- Xi-1 = Xi
        assignTo(sL, sL2);
        //OPTIMIZATION
        //Removes multiple occurence of t value, only keeping the best of each.
        sL = removeMultOcc(sL);
        //Keeps best state
        //sL = keepBestState(sL);
        currS = sL->head;
        //END OF OPTIMIZATION
        //Add curr Task time to Ak
        Ak += ctask->_dur;
        //Next list member
        currT = currT->next;
    }

    //std::cout << "Best States : \n" << listToString_State(sL) << " \n\n";

    sL = keepBestState(sL);

    std::cout << "Optimal Solution : \n" << stateToString((State*)sL->head->data) << " \n";

    return (State*)sL->head->data;
}

#endif // !TOOLS

我的代码有什么问题?

我的内存管理似乎有些问题,但我找不到在哪里。我非常感谢您的帮助!我正在使用 Visual Studio 2019。

标签: cliststructmemory-management

解决方案


推荐阅读