为什么我的类 std::vector 成员总是抛出段错误?
Why does my class std::vector member always throw a segfault?
我在SE上无休止地寻找为什么会发生这种情况的合乎逻辑的解释。 这可能是我忽略的非常简单的事情,但是我无法发现它,并且非常感谢对此的一些帮助。
上周,我实现了一个类来从.ini文件中读取系统调用的输出,然后查找所需信息并将其存储到自定义对象中,然后存储在 Config 类内的向量中。 它是一个单例配置类,为创建的自定义类的每个实例存储unique_ptr。
问题是,当我上周在我的笔记本电脑上实现这一点时,我对成员向量的读写问题为零,并且能够让它完全按照我的需要工作。 自从拉到我的台式计算机以来,这个向量以及我用作类成员的任何 STL 容器在我尝试在其上执行任何操作(甚至获取其大小(时都会引发分段错误。
我试图缩短下面的代码,只包含实际使用此向量的部分。 我已经用 A 替换了我的配置,用 T 替换了自定义类,无论我在哪里尝试使用我的成员容器,或者我添加到类的任何其他测试 STL 容器,我都会得到一个段错误。
作为记录,我将Qt与C++11一起使用。
更新:此示例在调试时在 c.cpp 的第 50 行以及尝试调用向量的任何位置中断。
调试在 stl_vector.h 中指向此行
// [23.2.4.2] capacity
/** Returns the number of elements in the %vector. */
size_type
size() const _GLIBCXX_NOEXCEPT
/*-> this line */ { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
主.cpp
#include "c.h"
int main(int argc, char *argv[])
{
C *c = C::getInstance();
delete c;
return 0;
}
t.h - 类存储文件中的信息
#include <string>
class T
{
public:
T();
bool Active();
std::string getA();
void setA(std::string);
private:
std::string a;
};
t.cpp
#include "t.h"
T::T()
{
}
bool T::Active()
{
if(a == "")
{
return false;
}
return true;
}
std::string T::getA()
{
return this->a;
}
void T::setA(std::string newa)
{
this->a = newa;
}
c.h - 类存储 T 对象并解析文件以获取信息
#include "t.h"
#include <QDebug>
#include <vector>
#include <algorithm>
#include <iostream>
#include <memory>
#include <sstream>
#include <fstream>
class C
{
public:
static C* getInstance();
private:
C();
static C* instance;
static bool init;
std::vector<std::unique_ptr<T>> t_list;
void readLines(const std::string&);
};
c.cpp
#include "c.h"
bool C::init = false;
C* C::instance = nullptr;
C::C()
{
system("echo this is a test command > a.ini");
instance->readLines("a.ini");
}
C* C::getInstance()
{
if(!init)
{
instance = new C;
init = true;
}
return instance;
}
void C::readLines(const std::string &path)
{
T* new_t;
std::ifstream file(path.c_str());
if(!file.is_open())
{
qDebug() << "Unable to open " << path.c_str();
}
std::ofstream o("test.txt");
std::string line;
while(std::getline(file, line))
{
// Split string before searching
std::stringstream ss(line);
std::string seg;
std::vector<std::string> split;
std::string left, right;
// Search patterns
size_t find_a = line.find("a");
size_t del = line.find(':');
if(find_a != std::string::npos)
{
o << "test_Size: " << t_list.size() << std::endl;
if(new_t->Active())
{
T* temp = new_t;
std::unique_ptr<T> move_t(temp);
t_list.push_back(std::move(move_t));
}
o << "test: " << t_list.size() << std::endl;
std::string n;
// Check if previous ahas any null elements
// Split string to find a
n = line.substr(line.find("a "));
n = n.substr(n.find(" ", +2));
new_t->setA(n);
}
else
{
continue;
}
}
// Add last a
T* t = new_t;
std::unique_ptr<T> move_t(t);
//t_list.push_back(std::move(move_t));
o << "a: " << t_list.back().get()->getA() << std::endl;
o << t_list.size() << std::endl;
o.close();
file.close();
}
代码更改后更新:
我现在看到两件事:一是C::readlines
中的new_t
从未初始化过,因此当稍后在函数中调用new_t->Active()
时,这可能会中断。但是,我相信您遇到的主要问题是在C::C()
,它说
instance->readLines("a.ini");
在执行的这一点上,C::instance
尚未初始化 - 您只是在构造稍后分配给它的对象。因此,readlines
调用中的this
无效,任何访问对象成员的尝试都将导致 UB。后一个问题可以通过调用来解决
readLines("a.ini");
在这种情况下,当前构造的对象(稍后将被instance
(用于this
。不过,我不知道你想在第一次发生什么,所以我只能说:如果你想有一个vector<unique_ptr<T>>
,你必须创建具有new T()
或(可以说是(std::make_unique<T>()
的T
类型的对象并将它们放在那里。
我还要说,这是在C++中实现单例的一种相当丑陋的方式。我的意思是,单例从来都不是很漂亮,但是如果你打算在C++中做到这一点,通常的方式就像C++单例设计模式的公认答案一样。
旧答案:
问题(如果是唯一的问题,我无法验证,因为您没有提供 MCVE(在行中
T move_t = new_T;
std::unique_ptr<Adapter> ptr_t(&move_t); // <-- particularly this one
m_ts.push_back(std::move(ptr_t));
您正在将指向本地对象的指针传递到std::unique_ptr
中,但std::unique_ptr
的全部目的是处理分配了new
的对象以避免内存泄漏。一旦离开此声明周围的范围,您传入的指针不仅无效,即使不是这种情况,unique_ptr
也会尝试在其生命周期结束时delete
不在堆上的对象。这两个问题都会导致未定义的行为。
对我来说,看起来你真的想使用std::vector<T>
而不是std::vector<std::unique_ptr<T>>
,但这是一个你必须自己回答的设计问题。
在这里回答我自己的问题。 我正在尝试从保存它的对象的构造函数中调用一个成员变量,因此我尝试访问的向量尚未实例化,并且不存在内存中。 这就是导致分段错误发生的原因,我正在尝试访问尚未分配的内存,因此作用于我的 C 类的任何成员的任何调用都会导致此问题。
我通过向类添加一个公共函数来解决此问题,该函数随后调用私有readLines()
函数。 我从将获得它所有权的对象调用该公共函数,并且由于这发生在实例化之后,因此内存是可访问的,问题消失了。
- 编写代码时C++出现错误:错误 1 错误 C2601:'circle':本地函数定义是非法的
- 如何摆脱C ++中的分段错误错误?
- Clang 8 带有静态 constexpr 和数组的链接器错误 - 错误是什么以及如何解决它?
- 为什么每当我尝试运行此链接列表删除功能时都会收到分段错误错误?
- 如何解决分段错误错误C++
- 作为参数模板的模板类:MSVC 错误 - 错误 C2977:模板参数过多 (C++98)
- 安卓工作室 |CPP 文件错误错误: 位图库中对"AndroidBitmap_unlockPixels"的未定义引用
- 卷曲给出分段错误错误
- 无法访问 Arduino 结构字段。错误"退出状态 1。xxxx 不命名类型"
- 错误错误 C2872:"布尔值":kinect.h 的不明确符号
- C++打印模板容器错误(错误:"运算符<<"的不明确重载)理解?
- 结构的分割错误错误
- 为什么此代码返回分段错误错误?
- 错误错误:无法编译内置功能
- 分段错误错误C++
- C++ 1Z 错误:错误:演绎指南中声明中的显式限定
- 使用对数据类型的向量的哈希表中的分段错误错误
- 为什么此代码会导致分段错误错误
- JNA结构字段值错误
- C++段故障错误