第一次,我这样编码(我正在做一个特里),当我调用add(“ 911”);当* str =='1'
时,我出现了分段错误struct Node {
int check, check2;
Node* chd[10];
Node() : check(0), check2(0), chd{0, } {}
~Node() {
for (int i = 0; i < 10; i++)
if (chd[i])
delete chd[i];
}
int add(char* str) {
if (!str[0])
return 0;
if (chd[*str-'0'] == 0) // here I got SIGSEGV
chd[*str-'0'] = new Node();
...
return chd[*str-'0']->add(++str);
}
}
然后我像这样固定那部分
int i = *str-'0';
if (chd[i] == 0)
chd[i] = new Node();
没有错误。
有什么区别?是什么使第一个代码产生错误?
(我正在解决ACM-ICPC>地区>欧洲>西北欧区域竞赛>北欧大学编程竞赛> NCPC 2007 A)
答案 0 :(得分:2)
return chd[*str-'0']->add(++str);
在您修改和使用str
无序列时包含不确定的行为。
您的“修复程序”具有经典的行为,可以将某些内容四处移动以隐藏未定义的行为。请记住,未定义的行为是未定义的。它不必崩溃。它甚至没有任何意义。而且最可怕的是它至少可以暂时满足您的期望。
一个简单的更改是:
return chd[*str-'0']->add(str+1);
答案 1 :(得分:0)
此行具有未定义的行为
return chd[*str-'0']->add(++str);
因为str
的修改和使用没有顺序。
快速解决方法是(当您指++
时不要说+ 1
):
return chd[*str-'0']->add(str + 1);
但是您也可以通过只计算一次相关索引来避免该问题(听起来这是您解决问题的方式,并且是更好的解决方案):
int add(char* str) {
if (!str[0])
return 0;
char c = str[0] - '0';
if (chd[c] == 0)
chd[c] = new Node();
...
return chd[c]->add(str + 1); // And ++str would also work...