处理核心转储条件
Handling core dump condition
我有一些简单的代码(这是我拥有的较大代码的较小示例(:
#include <iostream>
#include <unordered_map>
#include <list>
// List of blocks
std::list<struct Block> Blocks;
class ObjInfo
{
private:
int size;
public:
ObjInfo(int size){this->size = size;}
int get_size() {return size;}
};
struct Block
{
// name of the block
int x;
// Actual variable stack
std::unordered_map <int, ObjInfo*> objinfostack;
};
int main()
{
int x = 2;
while( x >= 0 )
{
Block b;
b.x = x;
b.objinfostack.insert(std::make_pair(x, new ObjInfo(4)));
--x;
Blocks.push_front(b);
}
for(std::list<struct Block>::iterator i = Blocks.begin(); i!=Blocks.end(); ++i)
{
std::cout << "here: " << i->objinfostack[1]->get_size() << 'n';
}
return 0;
}
关于代码中发生的事情的快速说明:
注意以下行导致seg fault
:
std::cout << "here: " << i->objinfostack[1]->get_size() << 'n';
由于无效访问而发生的发生:
i->objinfostack[1]
我将在Blocks
列表中得到类似的东西:
i->objinfostack[2], i->objinfostack[1]
我的问题是如何处理这种无效的条件。
如何处理这种无效条件
如果您不确定该条目是否存在,则不使用operator []
来处理此类条件。如果不存在密钥值,则operator []
将自动将条目插入地图。您无法更改此行为 - 当密钥不存在时,operator []
的工作方式就是为该值创建nullptr
,因为这是指针类型的零键值。
相反,您应该使用std::unordered_map::find()
测试键是否存在而不是使用[]
,并使用返回的迭代器(如果不是end()
(:
auto iter = i->objinfostack.find(1);
if ( iter != i->objinfostack.end())
std::cout << "here: " << iter->second->get_size() << 'n';
如果您真的想插入一个项目,如果密钥不存在,并且您希望对象指向某个地方,则需要明确调用insert()
:
i->objinfostack.insert({1, new ObjInfo(4)});
将会发生的是,插入始终检查以查看密钥条目是否存在,如果不存在,则将插入新的条目。因此,如果不存在,则上述代码将始终创建一个条目,如果条目已经存在,则将不存在任何条目。
然而,一个问题是,如果对象已经存在,则会发生内存泄漏,因为new
将在没有相应删除的情况下调用CC_11。要解决这个问题,您可以
1(将地图更改为将RAII类型存储为值类型(例如std::vector<ObjInfo>
std::shared_ptr
,STD :: unique_ptr`(或
2(检测未发生插入,因此分别分配的对象分别。
。auto new_ptr = new ObjInfo(4);
auto pr = i->objinfostack.insert({1, new_ptr});
if (!pr.second) // insert didn't happen
delete new_ptr;
但是,当然这很麻烦,可能要做的最简单的事情是首先使用std::map::find()
,如果找不到条目,则将/插入地图中分配/插入。
所以请您选择 -
1(如果条目不存在,则什么都不做(使用find(((或
2(如果条目不存在,请创建一个具有有效ObjInfo
的条目(使用insert()
,但请注意上面表达的警告(。
底线永远不会使用地图operator []
无条件地使用,除非您确定要自动创建一个具有默认构造或零定位值的新键。
索引无效,因此崩溃:
i->objinfostack[1]
将第一个块添加到列表中,将在地图中添加一个条目:
objinfostack[2] = {2, somePointer}
将添加第二个块:
objinfostack[1] = {1, somePointer}
因此,当您沿着列表走时,您最终将在仅插入索引[2]的块上访问索引[1]。结果,块将无效。如果您做了这样的事情,问题将消失:
for(std::list<Block>::iterator i = Blocks.begin(); i!=Blocks.end(); ++i)
{
std::cout << "Block....n";
for(auto& val : i->objinfostack)
{
std::cout << '[' << val.first << "] " << val.second->get_size() << 'n';
}
}
- 分段故障(堆芯转储)矢量
- Cppcheck生成xml转储文件
- 如何找出GDB的SIGTRAP核心转储的根本原因
- C++映射分割错误(核心转储)
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 浮点异常(核心转储)#694457
- 分段错误(核心转储)但无法弄清楚
- 链接到libkcapi时没有核心转储
- 检测到堆栈粉碎:已终止 中止(核心已转储)
- 正在处理故障(堆芯转储)
- 分段错误(核心转储) - 使用 SavedModel 的 Tensorflow C++ API 进行推断
- 我不知道为什么这段代码会让核心被转储?
- C++运行时错误与快速排序算法抛出堆栈转储错误
- 在基数排序中,我得到 munmap_chunk():无效指针和中止(核心转储).为什么?
- C++指针无法在函数外部传递值和分段错误(核心转储)错误
- cygwin_exception::open_stackdumpfile:将堆栈跟踪转储到 class4.exe.sta
- C++快速将 int 数组内容转储到文本文件中
- 合并排序:分段错误核心转储
- 处理核心转储条件