Правильное объявление unique_ptr массива из 1 элемента - PullRequest
0 голосов
/ 27 сентября 2018

Мне нужно использовать API как часть проекта, который включает класс ParamSet с методом, который определен следующим образом:

void AddString(const std::string &, std::unique_ptr<std::string[]> v, int nValues);

Цель метода - добавитьмассив строк в объекте для описания какого-либо параметра.Например, для объекта ParamSet может потребоваться параметр «имя файла», который указывает на массив строк nValues.

Однако, когда я пытаюсь передать метод a unique_ptr в массив, содержащий только 1 строку, код seg дает сбой при вызове деструктора для объекта ParamSet, если только я не определю unique_ptr вконкретный способ.

Следующий код вызывает ошибку сегмента при вызове Clear() или при return.

ParamSet badparam;
badparam.AddString("filename", unique_ptr<string[]> (new string("test")), 1);
badparam.Clear(); // <------ CAUSES SEG FAULT

Однако следующее не вызывает ошибку сегмента.

ParamSet testparam;
std::unique_ptr<std::string[]> strings(new std::string[0]); // DOH, should be string[1]
strings[0] = std::string("test");
testparam.AddString("filename", std::move(strings), 1);
testparam.Clear(); // <------ NO SEG FAULT

Я не понимаю, почему создание unique_ptr в строке, вызывающей AddString, приводит к сегментуошибка, но создание его вне вызова не делает.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Специализация массива std::unique_ptr требует, чтобы массив был выделен с new[], так как он использует delete[] по умолчанию для освобождения массива.

В первом примере вы выделяете одинstd::string объект с new, а не 1-элементный массив с new[].

Во втором примере вы выделяете 0-элементный std::string массив, но вам нужен 1-элементныйвместо массива.

Попробуйте вместо этого:

std::unique_ptr<std::string[]> strings(new std::string[1]); // <-- NOT 0!
// Or, if you are using C++14:
// auto strings = std::make_unique<string[]>(1);
strings[0] = "test";
testparam.AddString("filename", std::move(strings), 1);

В качестве альтернативы:

testparam.AddString("filename", std::unique_ptr<std::string[]>(new std::string[1]{"test"}), 1);
0 голосов
/ 27 сентября 2018

Проблема в том, что вы используете немассив new для выделения памяти, управляемой unique_ptr<T[]>, которая затем будет использовать массив delete[], вызывая неопределенное поведение.

Синтаксис может быть следующим:

badparam.AddString("filename", std::unique_ptr<std::string[]>(new std::string[1]{"test"}), 1);
...