我正在编写一个简单的内存数据库。它应该支持transaction
,这意味着BEGIN
命令会创建一个新块,其中的操作可以被ROLLBACK
命令取消。
我正在使用block
实现事务vector
列表。在BEGIN
的情况下,push_back()
该事务块中所有键的unordered_set
创建了一个新块。这被定义为vector<unordered_set<string>> key_in_blocks
以下是命令的示例。 SET
为变量设置值,GET
获取变量的值。
BEGIN
SET a 10
GET a <-- this prints 10
BEGIN
SET a 20
GET a <-- this prints 20
ROLLBACK
GET a <-- this prints 10
ROLLBACK <-- Segmentation Fault here!
首先有一个默认的block
,而keys_in_block看起来像[()]
,here()表示set
,[]表示vector
。
发布BEGIN
后,会创建一个新块,SET
会向该块添加一个键a
,因此keys_in_block = [(), ('a')]
。
下一个BEGIN
&amp; SET
部分类似,使keys_in_block
看起来像[(), ('a'), ('a')]
。
现在ROLLBACK
取消在最后一个块中完成的操作,keys_in_block
应为[(), ('a')]
,因为它是pop_back()
。
我认为我的计划在这一点上做了它需要做的事情。
在第二个ROLLBACK
上,它会引发分段错误,看起来我根本无法访问keys_in_block
变量。
以下是我的代码段。它在无限循环内运行,从用户那里获取命令。
} else if (command == "BEGIN") {
int num_blocks = keys_in_block.size();
keys_in_block.resize(num_blocks + 1); //new transaction block
} else if (command == "ROLLBACK") {
if (keys_in_block.size() <= 1) {
cout << "NO TRANSACTION" << endl;
}
else {
auto &recent_keys = keys_in_block.back();
// undo operations for keys in the most recent transaction block
for (const string &key : recent_keys) {
//...
//... a bunch of operations that undoes what's done
//... in the most recent transaction block.
recent_keys.erase(key); // erase all keys in the last entry in `keys_in_block`.
}
auto & aa = keys_in_block; //***Just for testing, not relevant to the program.
//This throws Segmentation Fault on second ROLLBACK.
keys_in_block.pop_back(); //Pop back the last transaction block.
}
}
在代码段中,我使用//***
标记了引发分段错误的位置。
我添加了该行,因为keys_in_block.pop_back()
引发了分段错误,并希望看到它是否仅通过访问它就会抛出seg错误。
对我来说,算法看起来绝对正确,我无法找出问题的原因。
当ROLLBACK
只有keys_in_block
个block
时,{p> pop_back()
无法执行,因此SET
不会成为问题。
如果您需要$(document).ready(function() {
var iArrayValue = 10000000;
setInterval(function() {
$("#example").sevenSegArray({
digits: 8,
value: iArrayValue
});
});
});
命令部分的代码,请告诉我,但我不认为该代码存在问题。
答案 0 :(得分:1)
我注释掉了recent_keys.erase(key);因为那不是必要的,而且有效!!然而,我无法弄清楚原因。
这是您的程序崩溃的原因,因为您在同时迭代容器时删除了该元素。 for (const string &key : recent_keys)
循环试图从开始到结束运行,但是你删除循环中的元素,以便迭代器变为无效,因此循环在尝试递增时不能继续并崩溃迭代器。
这很奇怪,因为recent_keys只是对向量中最后一个元素的引用,我正在使用erase删除向量中最后一个元素中的元素。你能解释一下发生了什么,以及如何避免犯同样的错误?
是recent_keys
是对向量的最后一个元素的引用,但是在迭代时不应该删除元素。如果你想避免犯同样的错误,那么再也不要这样做了。
在您的示例中,您可以迭代recent_keys
,然后让keys_in_block.pop_back()
进行清理。对于其他情况,您可能希望迭代容器并收集元素引用,然后在完成迭代容器后删除这些元素,您可以使用vector
&#39; s erase
结合{{1}完成这件事。