BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #94398同步于 2017/1/23
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

我可能用了假的c++11

chenxiansf
2017/1/23镜像同步19 回复
刷UVa OJ的时候遇到的超级诡异的问题,先上代码。(下面的是能AC的代码) #include <iostream> #include <string> #include <vector> #include <queue> using namespace std; struct Node { int left, right; int value; bool has_value; Node() { left = right = value = 0; has_value = false; }; }; vector<Node> tree; int root; int createNode() { tree.push_back(Node()); return (int)tree.size() - 1; } bool addNode(int value, string path) { int node = root, t; for (auto c : path) { if (c == 'L') { if (tree[node].left == 0) { t = createNode(); tree[node].left = t; //tree[node].left = createNode(); //把上面两行换成此行出错 } node = tree[node].left; } else if (c == 'R') { if (tree[node].right == 0) { t = createNode(); tree[node].right = t; //tree[node].right = createNode(); //把上面两行换成此行出错 } node = tree[node].right; } } if (tree[node].has_value) return false; tree[node].value = value; tree[node].has_value = true; return true; } int main() { string s; while (cin >> s) { tree.clear(); root = createNode(); bool failed = false; while (s != "()") { int index_comma = s.find(','); int value = stoi(s.substr(1, index_comma - 1)); string path = s.substr(index_comma + 1, s.size() - index_comma - 2); if (addNode(value, path) == false) { failed = true; } cin >> s; } queue<int> Q; vector<int> ans; Q.push(root); while (!Q.empty()) { int node = Q.front(); Q.pop(); if (!tree[node].has_value) { failed = true; break; } ans.push_back(tree[node].value); if (tree[node].left > 0) Q.push(tree[node].left); if (tree[node].right > 0) Q.push(tree[node].right); } if (failed) { cout << "not complete" << endl; } else { if (!ans.empty()) { cout << ans[0]; for (int i = 1; i < ans.size(); i++) { cout << ' ' << ans[i]; } } cout << endl; } } return 0; } 代码中27行和35行是原先写出来的,在vs2015上运行正常,结果提交到oj说Runtime Error。调试了半天也没发现问题,后来我一想调试好歹要用一样的编译器啊。然后打开clion换成gcc,果然运行时错误。 下面是oj上的gcc参数 C++11 5.3.0 - GNU C++ Compiler with options: -lm -lcrypt -O2 -std=c++11 -pipe -DONLINE_JUDGE 我用clion调试的时候发现运行时错误的原因在于代码中27行和35行调用createNode()时虽然能正常返回值,但它不会赋值给左边的tree[node].left,这简直太奇怪了。 我尝试着更换成先获取返回值再赋值,如上面代码所示,结果竟然可以了,一提交到oj上也AC了。 但就是非常不明白啊,难道这是gcc的bug? 求各位大神指点[ema13] 输入输出样例如下: Sample Input (11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) () (3,L) (4,R) () Sample Output 5 4 8 11 13 4 7 2 1 not complete 原题如下: 好吧,这不是重点
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
chenxiansf机器人#1 · 2017/1/23
@nuanyangyang
nuanyangyang机器人#2 · 2017/1/23
tree[node].left = createNode(); C++11没有规定先求赋值表达式左边还是右边的值(C++17先左边,后右边)。假如先求了左边的值。 左边是一个l-value,是tree这个vector里某个元素的存储空间。 但是,右边createNode()有副作用,它在push_back的时候,会造成vector大小变化。内部实现的方法,可能是把原来所有的存储空间拷贝到新分配的更大的数组中,然后把原来的存储空间释放。 也就是说,如果createNode()里面的push_back造成了vector大小变化,赋值运算符左边的l-value就指向一个已经被释放了的空间了。于是,有可能segmentation fault。
chenxiansf机器人#3 · 2017/1/23
给跪了,暖神太6了,受我一拜 【 在 nuanyangyang 的大作中提到: 】 : tree[node].left = createNode(); : C++11没有规定先求赋值表达式左边还是右边的值(C++17先左边,后右边)。加入先求了左边的值。 : 左边是一个l-value,是tree这个vector里某个元素的存储空间。 : ...................
nuanyangyang机器人#4 · 2017/1/23
顺便秀一下比较摩登的语言: Java: int addElem(ArrayList<Integer> ar, int num) { ar.add(num); return ar.size(); } void main() { ArrayList<Integer> ar = new Arraylist<Integer>(); ar.set(0, 0); ar.set(1, 1); ar.set(2, 2); for (int i = 0; i < 3; i++) { ar.set(i, addElem(i)); } } ar.set(i, addElem(i));一定会先求出addElem(i)的值,然后调用ar.set方法。顺序已经保证了。 Scala: val ar = ArrayBuffer(0,1,2); for (i <- 0 until 3) { ar(i) = addElem(i) } 一样。Scala里,ar(i)=addElem(i)是语法糖,会展开成ar.update(i, addElem(i)) 【 在 chenxiansf 的大作中提到: 】 : 刷UVa OJ的时候遇到的超级诡异的问题,先上代码。(下面的是能AC的代码)
qiukun机器人#5 · 2017/1/23
Go 也( 【 在 nuanyangyang 的大作中提到: 】 : 顺便秀一下比较摩登的语言: : Java: : [code=java] : ...................
nuanyangyang机器人#6 · 2017/1/23
顺便说一下,Rust也有和C++一样的问题。rust的复制表达式的求值顺序也没有规定。所以对Vec的push也会出现类似的重新分配问题。官方开发人员内部讨论帖: https://internals.rust-lang.org/t/rust-expression-order-of-evaluation/2605
chenxiansf机器人#7 · 2017/1/23
我要立志学Scala了 【 在 nuanyangyang 的大作中提到: 】 : 顺便秀一下比较摩登的语言: : Java: : [code=java] : ...................
nuanyangyang机器人#8 · 2017/1/23
加油 【 在 chenxiansf 的大作中提到: 】 : 我要立志学Scala了
bond1993机器人#9 · 2017/1/23
感觉轮子哥有暖神的感觉,我要向两位学习~