@FaulerAffe
-

Как исправить ошибку EXC_BAD_ACCESS (code=1, address=0x0)?

Хочу сделать визуализацию сортировки слиянием на SFML. Уже сделал визуализацию быстрой сортировки, там всё работает отлично, причем вроде действия те же. У меня есть массив из структур, структура выглядит так:
struct elem2
{
    sf::RectangleShape shape;
    int value;
};

Вот основная функция сортировки:
void merge_sort (elem2 a[], int p, int r)
{
    if (p < r)
    {
        int q = (p + r)/2;
        merge_sort(a, p, q);
        merge_sort(a, q + 1, r);
        merge(a, p, q, r);
    }
}

вроде ничего необычного, рекурсия используется и в быстрой сортировке, там всё работает. В самом начале вспомогательной функции, при первом же её вызове всё вылетает с ошибкой EXC_BAD_ACCESS (code=1, address=0x0), что, вроде как, обычно говорит, что я вышел за границы массива. Вылетает вот здесь:
int merge (elem2* a, int p, int q, int r)
{
    elem2* pq = (elem2*)malloc(sizeof(elem2) * ((q - p) + 1));
    elem2* qr = (elem2*)malloc(sizeof(elem2) * (r - q));
    sf::Vector2f pos;
    
    int j = p;
    for (int i = 0; i < q - p + 1; i++)
    {
        pq[i] = a[j];
        j++;
    }
    
    j = q + 1;
    for (int i = 0; i < r - q; i++)
    {
        qr[i] = a[j];
        j++;
    }
...

При первом вызове выделяется место под два массива длиной в один элемент, я проверил через отладчик, с индексами точно всё в порядке, ничего за границы не выходит. При этом вылетает то в первом цикле, то во втором, чаще в первом. Хотя по сути ничего странного вроде как нет – просто копируем содержимое из данного массива в только что созданный. Далее я попробовал изменить структуру на вот такую:
struct elem2
{
    int shape;
    int value;
};

Всё заработало. При этом проблема именно с фигурами, то есть, допустим, sf::CircleShape тоже не работает, а вот если туда вписать sf::Vector2f, то всё запускается. В чём может быть проблема?
  • Вопрос задан
  • 131 просмотр
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Вы "создаете" класс sf::RectangleShape через malloc в составе временных массивов pq, qr. Он оказывается заполнен мусором. Нарушены какие-то его внутренние инварианты. Может быть куча проблем: начиная от того, что там переопределен оператор присванивания, который должен что-то где-то почистить, заканчивая тем, что таблица виртуальных методов у класса будет испорчена. Любая попытка сделать что угодно с таким экземпляром класса - скорее всего неопределенное поведение.

Если уж вы используете классы из C++, то выделять память надо через new[], а не malloc. Тогда экземпляр класса создасться нормально и конструктор вызовется.

Можно было бы подумать, что memmove решил бы вашу проблему - но, опять же, при этом нарушаются внутренние инварианты. Какой-нибудь unique_ptr внутри будет уже не уникальным. Такие операции работы с памятью можно делать только для POD (Plain old data) - структур состоящих из структур, массивов и базовых типов.

Или, еще лучше использовать vector для временных массивов. Тогда вам не придется заботиться об освобождении памяти. Еще, вместо копирования можно использовать std::move, может работать бысрее, если эти sf классы имеют более эффективные операторы перемещения.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы