У меня есть метод, который принимает 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
Любая помощь приветствуется.
Если не знали, не удаляйте.
Предоставленный фрагмент — это все, что у меня есть для модульного теста. Я ничего не удаляю явно, поэтому не знаю, как избежать удаления скрытый.
@MatinKh unique_ptr
деструктор delete[]
по умолчанию является удерживаемым указателем, если вы не предоставите другой deleter
.
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[]
и метод только читает данные. Не могли бы вы пояснить решение?
Добавлено, как получить правильно размещенную копию тестовых данных.
@MatinKh: unique_ptr
вызывает удаление своего указателя, когда он уничтожается. На самом деле это вся цель unique_ptr
. Поэтому, если вы не создали указатель через new
или make_unique
, не сохраняйте его в unique_ptr
.
Я не думаю, что копирование данных в unique_ptr решит проблему. Я получаю эту ошибку: double free or corruption (fasttop): 0xb87b73a0
, независимо от того, копирую ли я данные или нет. Одна только эта строка auto testBytesPtr = std::make_unique<uint8_t[]>(...);
выдает мне ошибку.
Эта строка безобидна, она просто создает unique_ptr, владеющий новой частью памяти. Но .reset(somelocal)
это плохо.
указывать
unique_ptr
на объект в автоматическом хранилище без предоставления ничего не делающего удаления — плохая идея. Не удаляйте стек.