unique_ptr 数组访问分段错误
unique_ptr array access Segmentation fault
当我通过unique_ptr访问数组元素时,出现segfault,通过vs调试,发现std::unique_ptr p的类型和数据很奇怪,我觉得是应该是一个数组,但是看起来像一个字符串,无论我压入多少个元素,p的数据都指向“to”,其他元素是看不到的。
代码
#include <memory>
#include <string>
#include <assert.h>
#include<vector>
#include<iostream>
#include <stack>
#include <string>
#include <sstream>
template <typename T>
class FixedCapacityStockOfStrings {
public:
FixedCapacityStockOfStrings(const int cap) {
p = std::make_unique<T[]>(cap);
MAX = cap;
}
bool isEmpty() {
return N == 0;
}
size_t const size() { return N; }
void push(T& item){
//assert(N < MAX - 1);
if (N == MAX-1) resize(2 * MAX);
p[N++] = item;
}
T pop() {
assert(N > 0);
T item = p[--N];
p[N] = nullptr;//Segmentation fault is here
if ( N <= MAX / 4) resize(MAX / 2);
return item;
}
size_t max() const { return MAX; }
void clear() {
N = 0;
}
private:
void resize(int max) {
auto t = std::make_unique<T[]>(max);
for (int i = 0; i < N; i++) {
t[i] = p[i];
}
p.reset();
p = std::move(t);
MAX = max;
}
std::unique_ptr<T[]> p;
size_t N,MAX;
};
int main() {
FixedCapacityStockOfStrings<std::string> s(100);
std::string line,item;
while (std::getline(std::cin, line)) {
std::istringstream items(line);
while (items >> item) {
if (item != "-")
s.push(item);
else if (!s.isEmpty()) std::cout << s.pop() << " ";
}
std::cout << "(" << s.size() << " left on stack)" << " max stack : " << s.max() << std::endl;
s.clear();
}
}
p
包含 std::string 的数组。当您分配 p[N] = nullptr
时,您将一个 C 字符串分配给 std::string。 C 字符串是指向以 null 结尾的字符数组的指针,nullptr 不是有效的 C 字符串。
请注意 p[N]
的类型 std::string&
for T
= std::string
,所以
p[N] = nullptr;
确实是使用参数 nullptr
调用 std::string::operator=(const char*)
。这不是您可以传递给该赋值运算符的参数;它需要一个以 0 结尾的字符串。
编辑:根据@Remy Lebeau
的建议进行了改进
你应该选择
p[N] = T{};
相反。
在语句 p[N] = nullptr;
中,您将 nullptr
分配给 std::string
,即 未定义行为。
您忘记在构造函数中初始化N
,所以它是一个垃圾值,读取它是未定义的行为。
当我通过unique_ptr访问数组元素时,出现segfault,通过vs调试,发现std::unique_ptr
代码
#include <memory>
#include <string>
#include <assert.h>
#include<vector>
#include<iostream>
#include <stack>
#include <string>
#include <sstream>
template <typename T>
class FixedCapacityStockOfStrings {
public:
FixedCapacityStockOfStrings(const int cap) {
p = std::make_unique<T[]>(cap);
MAX = cap;
}
bool isEmpty() {
return N == 0;
}
size_t const size() { return N; }
void push(T& item){
//assert(N < MAX - 1);
if (N == MAX-1) resize(2 * MAX);
p[N++] = item;
}
T pop() {
assert(N > 0);
T item = p[--N];
p[N] = nullptr;//Segmentation fault is here
if ( N <= MAX / 4) resize(MAX / 2);
return item;
}
size_t max() const { return MAX; }
void clear() {
N = 0;
}
private:
void resize(int max) {
auto t = std::make_unique<T[]>(max);
for (int i = 0; i < N; i++) {
t[i] = p[i];
}
p.reset();
p = std::move(t);
MAX = max;
}
std::unique_ptr<T[]> p;
size_t N,MAX;
};
int main() {
FixedCapacityStockOfStrings<std::string> s(100);
std::string line,item;
while (std::getline(std::cin, line)) {
std::istringstream items(line);
while (items >> item) {
if (item != "-")
s.push(item);
else if (!s.isEmpty()) std::cout << s.pop() << " ";
}
std::cout << "(" << s.size() << " left on stack)" << " max stack : " << s.max() << std::endl;
s.clear();
}
}
p
包含 std::string 的数组。当您分配 p[N] = nullptr
时,您将一个 C 字符串分配给 std::string。 C 字符串是指向以 null 结尾的字符数组的指针,nullptr 不是有效的 C 字符串。
请注意 p[N]
的类型 std::string&
for T
= std::string
,所以
p[N] = nullptr;
确实是使用参数 nullptr
调用 std::string::operator=(const char*)
。这不是您可以传递给该赋值运算符的参数;它需要一个以 0 结尾的字符串。
编辑:根据@Remy Lebeau
的建议进行了改进你应该选择
p[N] = T{};
相反。
在语句 p[N] = nullptr;
中,您将 nullptr
分配给 std::string
,即 未定义行为。
您忘记在构造函数中初始化N
,所以它是一个垃圾值,读取它是未定义的行为。