Reputation: 13
I need to use an API as part of a project that includes a class called ParamSet
with a method that is defined as the following:
void AddString(const std::string &, std::unique_ptr<std::string[]> v, int nValues);
The purpose of the method is to add an array of strings to the object to describe some parameter. For example a ParamSet
object could require a "filename" parameter that points to an array of a nValues
strings.
However, when I try and pass the method a unique_ptr
to an array containing only 1 string, the code seg faults upon calling the destructor for the ParamSet
object unless I define the unique_ptr
in a specific way.
The following code causes a seg-fault upon calling Clear()
or on return
.
ParamSet badparam;
badparam.AddString("filename", unique_ptr<string[]> (new string("test")), 1);
badparam.Clear(); // <------ CAUSES SEG FAULT
However the following does not cause a 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
I don't understand why creating the unique_ptr
in the line calling AddString
leads to a seg fault, but creating it outside of the call to does not.
Upvotes: 1
Views: 68
Reputation: 596397
The array specialization of std::unique_ptr
requires the array to be allocated with new[]
, as it uses delete[]
by default to free the array.
In your first example, you are allocating a single std::string
object with new
, not a 1-element array with new[]
.
In your second example, you are allocating a 0-element std::string
array, but you need a 1-element array instead.
Try this instead:
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);
Alternatively:
testparam.AddString("filename", std::unique_ptr<std::string[]>(new std::string[1]{"test"}), 1);
Upvotes: 0
Reputation: 141598
The problem is that you use non-array new
to allocate memory managed by unique_ptr<T[]>
which will then go on to use array delete[]
, causing undefined behaviour.
The syntax could be:
badparam.AddString("filename", std::unique_ptr<std::string[]>(new std::string[1]{"test"}), 1);
Upvotes: 1