Использование qsort для сортировки пользовательского ADT, возвращающего segfault в C? - PullRequest
0 голосов
/ 26 апреля 2020

Я использовал qsort для сортировки моего массива в C (пользовательская реализация) по символам, но он возвращает ошибку сегмента, и я не совсем уверен, почему.
Кажется, что он пытается получить доступ указатель на элемент, который уже был удален.

Буквальная инициализация:

Literal *newLiteralStruct (char *name, int i){
    Literal *this = malloc(sizeof(Literal));
    this->name = name;
    this->isNegative = i; 
    return this;
}

Функция сортировки:

int sort(const void *struct1, const void *struct2){
    Literal* literalStruct1 = *(Literal**)struct1;
    Literal* literalStruct2 = *(Literal**)struct2;
    return strcmp(literalStruct1->name, literalStruct2->name);
}

Вызов метода:

{
                printf("Moving onto propagation..\n");
                Literal *literal = findNextUnitLiteral(allClauses);
                appendArrayList(unitLiterals, literal);
                checkForLiteralsInClauses(literal, allClauses);

                }
            while (findNextUnitLiteral(allClauses) != NULL);
        }
        unsigned int arraySize = size(unitLiterals);
        qsort((void*)unitLiterals, arraySize, sizeof(Literal*), &sort);
        for (unsigned int i = 0; i < size(unitLiterals); i++){
            Literal *literal = get(unitLiterals, i);
            printf("%s", literal->name);
}

Полная функция, которая может вызвать проблемы:

void checkForLiteralsInClauses(Literal *literal, arrayList *clauseArray){
    Literal *literalToCheck;
    printf("Literal being propagated: ");
    printCharacterAndSign(literal);

    unsigned int clauseArraySize = size(clauseArray);
        for (unsigned int i = 0; i<clauseArraySize; i++){
            arrayList * literalArray = get(clauseArray, i);
            unsigned int literalArraySize = size(literalArray);
            for (unsigned int j = 0; j < literalArraySize; j++){
                literalToCheck = get(literalArray, j);
                if (literalToCheck == NULL){
                    break;
                }

                if ((strcmp(literalToCheck->name, literal->name)==0) && literalToCheck->isNegative != literal->isNegative){
                    printf("Literal identified: ");
                    printCharacterAndSign(literalToCheck);
                    printf("This is a converse literal. The literal in the clause will now be removed.\n");
                    removeFromArrayList(literalArray, j);
                    if (size(literalArray) == 0){
                        printf("contradiction");
                        printf("-");
                        exit(EXIT_SUCCESS);
                    }
                   else if (size(literalArray) == 1){
                        printf("This is now a unit literal");
                        appendArrayList(clauseArray, literalArray);  
                    }
                }
                else if ((strcmp(literalToCheck->name, literal->name)==0 && literalToCheck->isNegative == literal->isNegative)){
                    printf("Literal identified: ");
                    printCharacterAndSign(literalToCheck);
                    printf("Same literal. The full clause will now be removed.\n");
                    removeFromArrayList(literalArray, j);
                    // destroyArrayList(literalArray);
                    removeFromArrayList(clauseArray, i--);
                    if (literalToCheck == 0){
                        break;
                    }
                }
                else if (strcmp(literalToCheck->name, literal->name) != 0){
                    printf("Literal identified: ");
                    printCharacterAndSign(literalToCheck);
                    printf("No match. Moving on!\n");
                }
            }
        }
}

Реализация ArrayList:

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "ArrayList.h"

#define initialCapacity 10
/*
defining a function that copies (length) number of bytes from the pointer of the source to the pointer of the destination
mainly used for removing functions
*/
#define arrayListShift(s, offset, length) memmove((s)+offset, (s), (length)*sizeof(s));

/**
creating a new arrayList as defined in arraylist.h
allocates memory for the initialCapacity of the array, as specified above
initializes the size of the array as 0, as no elements have been added
the maximum capacity at the start is the pre-defined initial capacity
*/

arrayList *createNewArrayList(){

    arrayList* arrayList = malloc(sizeof(arrayList));
    arrayList->size = 0;
    // Allocate the array
    arrayList->element = malloc(sizeof(void*) * initialCapacity);
    assert(arrayList->element);
    arrayList->maxCapacity = initialCapacity;
    return arrayList;
} 


void appendArrayList(arrayList * arrayList, void * item ) {

    if (arrayList->size == arrayList->maxCapacity){
        arrayList->element = realloc(arrayList->element, 2*arrayList->maxCapacity * sizeof(void*));
        arrayList->maxCapacity *= 1.5;
    }
    arrayList->element[arrayList->size++] = item;
}

/**
 * remove an element from the array at a specified index position
 * using memmove to shift all the following elements back by an index position
 */ 

void removeFromArrayList(arrayList *arrayList, unsigned int index){
    unsigned int size = arrayList->size;
    for (unsigned int i = index; i < (size-1); i++){
        arrayList->element[i] = arrayList->element[i+1];
    }
    arrayList->size--;
}

void removeByPointer(arrayList*arrayList, void*pointer){
    unsigned int num = arrayList->size;
    for(unsigned int i = 0; i<num; i++){
        if (arrayList->element[i] == pointer){
            removeFromArrayList(arrayList, i);
            break;
        }
    }
}

/**
 * clear the array of all its elements
 */
void clearArrayList(arrayList*arrayList){
    arrayList->size = 0;
}

/**
 * return the size of the array
 */
unsigned int size(arrayList*arrayList){
    return arrayList->size;
}

/**
 * return the maxCap of the array
 */
unsigned int maxCapacity(arrayList*arrayList){
    return arrayList->maxCapacity;
}

void *get(arrayList* arrayList, unsigned int index)
{
    return arrayList->element[index];

}

/**
 * free all the memory being used up by the arraylist
 */
void destroyArrayList(arrayList *arrayList){
    free(arrayList->element);
    free(arrayList);
}
...