Ошибка сегментации в моем перераспределении класса ArrayList - PullRequest
0 голосов
/ 06 июля 2018

В целях обучения я пытаюсь создать примитивный класс ArrayList с возможностью добавления элементов и изменения размера при необходимости. В настоящее время мне удалось создать конструктор и перегрузить оператор доступа к массиву, а также добавить функцию append для добавления элементов в конец массива. Однако после запуска realloc программа завершает работу с Segmentation Fault: 11. Как ни странно, если я изменяю свой код, при первом его выполнении не возникает ошибки сегментации; только при перезапуске исполняемого файла происходит сбой, поэтому я подозреваю, что мой free() вызов не работает должным образом. Кажется, что все элементы до перераспределения были успешно добавлены.

Мой класс определен в файле .cpp, потому что определения шаблонов не могут быть разбиты на заголовок и другой файл.

structures.cpp

#include <cstdlib>
#include <stdexcept>

template<typename T> class ArrayList {
    private:
        T* pointer;
        unsigned short space;
    public:
        ArrayList();
        ~ArrayList();
        T& operator[](unsigned short index);
        const T& operator[](unsigned short index) const; 
        unsigned short length;
        void append(T element);
};

template<typename T> ArrayList<T>::ArrayList() {
    length = 0;
    space = 10;
    pointer = (T*)malloc(space*sizeof(T));
}

template<typename T> ArrayList<T>::~ArrayList() {
    free(pointer);
}

template<typename T> T& ArrayList<T>::operator[](unsigned short index) {
    if (index > length) throw std::out_of_range("Index out of bounds.");
    return *(pointer + sizeof(T)*index);
}

template<typename T> void ArrayList<T>::append(T element) {
    if (length == space) {
        space *= 2;
        pointer = (T*)realloc(pointer, sizeof(T)*space);
    }
    *(pointer + sizeof(T)*length) = element;
    ++length;
}

main.cpp

#include <iostream>
#include "structures.cpp"

int main(int argc, char** argv) {
    ArrayList<unsigned> arr;
    int l = 11;
    for (int i = 0; i < l; ++i) {
        std::cout << "Current index: " << i << std::endl;
        arr.append(i);
    }
    std::cout << "Finished writing to array" << std::endl;
    for (int i = 0; i < l; ++i) {
        std::cout << "Index: " << i << " Value: " << arr[i] << std::endl;
    }
    return 0;
}

Выход:

Current index: 0
Current index: 1
Current index: 2
Current index: 3
Current index: 4
Current index: 5
Current index: 6
Current index: 7
Current index: 8
Current index: 9
Current index: 10
Segmentation fault: 11

1 Ответ

0 голосов
/ 06 июля 2018

Проблема здесь (в вашей функции append):

*(pointer + sizeof(T)*length) = element;

Вы забыли, что pointer - это указатель (первый элемент) массива T элементов, а не массива байтов. То, что вы делаете, (точно) равно

pointer[sizeof(T)*length] = element;

, что явно неверно и может легко выйти за пределы и привести к неопределенному поведению .

Правильный путь это просто

pointer[length] = element;

Или, если вы вынуждены использовать явную арифметику указателей (я не вижу другой причины)

*(pointer + length) = element;
...