Недопустимая ошибка указателя при использовании unique_ptr в тестах

У меня есть метод, который принимает std::unique_ptr<uint8_t[]> в качестве входных данных и обрабатывает его. В моем модульном тесте

Вот как я создаю и инициализирую этот аргумент: (на куча)

uint8_t testBytes[] = {1, 2, 3, 4};
std::unique_ptr<uint8_t[]> testBytesPtr = std::make_unique<uint8_t[]>(4);
testBytesPtr.reset(testBytes);

И он передается методу вида:

myClass.processData(std::move(testBytesPtr));

В конце моего модульного теста я получаю следующее сообщение об ошибке:

free(): invalid pointer: 0xbed6b8c0


Вот как выглядит мой модульный тест:

#include "gtest.h"
#include "gmock.h" // for some deps

//...

TEST(MyClassUnittests, test1) {
    // Initializing the byte array.
    uint8_t testBytes[] = {1, 2, 3, 4};
    std::unique_ptr<uint8_t[]> testBytesPtr = std::make_unique<uint8_t[]>(4);
    testBytesPtr.reset(testBytes);

    EXPECT_TRUE(myClass.processData(std::move(testBytestPtr));
}

Я также должен отметить, что если testBytes инициализированы на куча (например, uint8_t* testBytes = new uint8_t()), сообщение об ошибке становится

double free or corruption (fasttop): 0xb75c1e18

Любая помощь приветствуется.

указывать unique_ptr на объект в автоматическом хранилище без предоставления ничего не делающего удаления — плохая идея. Не удаляйте стек.

user4581301 07.04.2019 17:37

Если не знали, не удаляйте.

Borgleader 07.04.2019 17:38

Предоставленный фрагмент — это все, что у меня есть для модульного теста. Я ничего не удаляю явно, поэтому не знаю, как избежать удаления скрытый.

Matin Kh 07.04.2019 18:16

@MatinKh unique_ptr деструктор delete[] по умолчанию является удерживаемым указателем, если вы не предоставите другой deleter.

Remy Lebeau 07.04.2019 20:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
669
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

delete []-иметь что-то, что не new []-ed и не принадлежит вам, категорически противопоказано.

Посмотрите на эти строки:

uint8_t testBytes[] = {1, 2, 3, 4};
std::unique_ptr<uint8_t[]> testBytesPtr = std::make_unique<uint8_t[]>(4);
testBytesPtr.reset(testBytes);

Удаление ненужного эфемерного динамического распределения оставляет:

uint8_t testBytes[] = {1, 2, 3, 4};
std::unique_ptr<uint8_t[]> testBytesPtr(testBytes);

Что вызывает Undefined Behavior при срабатывании dtor.

По общему признанию, вы перемещаете std::unique_ptr один раз, но это просто смещает точную точку, в которой происходит взрыв.

Учитывая функцию, которую вы хотите протестировать, попробуйте это, чтобы получить правильно выделенную копию тестовых данных:

uint8_t testBytes[] = {1, 2, 3, 4};
auto testBytesPtr = std::make_unique<uint8_t[]>(std::size(testBytes));
std::copy(std::begin(testBytes), std::end(testBytes), &testBytesPtr[0]);

Спасибо, что объяснили, в чем проблема. Однако мне все еще неясно, как решить проблему. Я ничего не делаю явно delete[] и метод только читает данные. Не могли бы вы пояснить решение?

Matin Kh 07.04.2019 18:20

Добавлено, как получить правильно размещенную копию тестовых данных.

Deduplicator 07.04.2019 18:33

@MatinKh: unique_ptr вызывает удаление своего указателя, когда он уничтожается. На самом деле это вся цель unique_ptr. Поэтому, если вы не создали указатель через new или make_unique, не сохраняйте его в unique_ptr.

Zan Lynx 07.04.2019 19:04

Я не думаю, что копирование данных в unique_ptr решит проблему. Я получаю эту ошибку: double free or corruption (fasttop): 0xb87b73a0, независимо от того, копирую ли я данные или нет. Одна только эта строка auto testBytesPtr = std::make_unique<uint8_t[]>(...); выдает мне ошибку.

Matin Kh 08.04.2019 18:38

Эта строка безобидна, она просто создает unique_ptr, владеющий новой частью памяти. Но .reset(somelocal) это плохо.

Deduplicator 08.04.2019 22:28

Другие вопросы по теме