一个 C++程序中奇怪的数值变换

2014-12-13 13:22:04 +08:00
 razrlele
昨天在写Uvaoj上面的题目的时候自己又写出了一个奇怪的代码, 我在进行一个正常的strcpy操作的时候, for循环里面的i的值却发生了莫名其妙的变化, 从当前值突然变成一个五位数, 最后直接导致程序运行的时候出现segment fault, strcpy里面没有跟i相关的任何操作, 并且更加诡异的是, 两台不同的电脑运行的时候出错的地方都不一样, 最后变成的五位数也都不一样.

运行的环境都是Ubuntu 14.04+ g++4.8.2 debug用的也都是gdb

具体的说明在这里(因为篇幅太长所以不好贴在V2ex上面): http://blog.razrlele.com/strange0/

PS:这一道题目我已经AC了, 所以并不是在伸手, 只是对于自己出现过的这个问题感到非常疑惑, 自己调试了很多遍也没发现问题出在哪里.

直接把全部代码贴出来了(不然好像难以重现bug), 所以可能会花比较长的时间来了解这个问题, 希望周末比较闲的V友可以帮忙看看, 谢谢!
2490 次点击
所在节点    问与答
17 条回复
xdeng
2014-12-13 13:29:13 +08:00
字节对齐 或者这个数的附近变量溢出了
razrlele
2014-12-13 13:34:17 +08:00
@xdeng ....那平时应该怎么注意防范啊...
aaaa007cn
2014-12-13 14:02:35 +08:00
> strcpy(tmpb, top(pb));
strcpy 是一直复制到 \0 为止
看看 top(pb) 返回的是什么,它的 \0 到哪里为止?

> 另外问题就好像出现在strcpy上面, 把strcpy换成了自己构造的函数过后i值就没有出现异样.
你自己构造的长什么样
fliar
2014-12-13 14:10:25 +08:00
你的char数组都很短,string是以/0结尾,scanf应该不会检查越界,尝试从这边下手
razrlele
2014-12-13 14:12:09 +08:00
@aaaa007cn
抱歉后来构造的代码在解题报告里面忘记贴上去了~

这是自己后来构造的函数

void cpycards(char* a, char* b)
{
a[0] = b[0];
a[1] = b[1];
return ;
}

嗯。。。top返回的是一个字符串的地址。。。

在gdb调试的时候确实有好像有发现过top(pb)直接返回了模拟的堆栈里面的所有字符(按道理应该只返回两个字符)。。。

所以应该是在我用strcpy操作字符串不当?
aaaa007cn
2014-12-13 14:17:23 +08:00
那就是 strcpy 越界了啊
因为它要一直拷贝到 top(pb) 的 \0 为止
你这里可以 memcpy(tmpb, top(pb), 2);

像 @fliar 所说,scanf 也一样有越界的问题
不过这个要看你的输入
razrlele
2014-12-13 14:26:18 +08:00
@fliar
@aaaa007cn

scanf应该没有问题, 见我已经AC的代码里面用着就很正常 http://yuyue.be/uvaoj127/
aaaa007cn
2014-12-13 14:38:15 +08:00
没出现问题 不等于 没有问题
因为 scanf 出不出问题和你的输入有关
在输入已知的情况下
scanf 的问题更加隐蔽

在 vc 中 scanf 和 strcpy 一样都会报 C4996 警告的
tomriddle
2014-12-13 15:01:54 +08:00
尽量不要混写C++和C,用C++就要尽量避免使用C函数,如果非要用,也最好封装起来用。
razrlele
2014-12-13 15:04:06 +08:00
@tomriddle
唔。。。现在主要还是在训练算法相关,工程项目还没有涉及过。。。

话说混起来用的话在工程项目中会出现什么问题么?
tomriddle
2014-12-13 15:19:12 +08:00
@razrlele 比方说 int class = 0; 在C中可以通过编译的,C++就是纯错误了。再比方std::string 无论是本身运算速度和开发效率char*都比不了的。还有如果非要在C++中放入纯C代码,需要用extern "C"来包裹,而且还要放在#ifdefine __cplusplus里面,非常麻烦。我觉得你如果用C++ 和STL来写这些会极大提高速度的,省下来的精力可以多做几道题。只有真正核心算法才去想办法优化。
razrlele
2014-12-13 15:22:30 +08:00
@tomriddle 我用STL的stack超时了。。。

据网上所说stack确实是慢了一点(不过只限于这道题)。。。

看来ACM代码和实际的应用还是蛮大差距的
jiang42
2014-12-13 15:41:06 +08:00
@razrlele 我恰好也做过这道题。。。为什么我用的stack AC了
tomriddle
2014-12-13 16:08:40 +08:00
@razrlele 那如果非要纯C的话就尽量代码写统一,避免使用C++。超时的话估计是人家编译器比较老吧。我这几年经验就是开发速度和执行速度一起考虑才是真正的编程语言效率,其实我更推荐用python编这些题目。
razrlele
2014-12-13 16:23:12 +08:00
@jiang42

我是看discuss里面说stack很慢, 然后搜的解题报告也没几个用stack的, 我用stack写的代码TLE也可能是我自己哪个地方写错了(我直接给删了所以现在也不知道)

你AC的代码运行时间是多少?
jiang42
2014-12-13 16:37:21 +08:00
@razrlele 我不仅用了stack,还用了vector。。。运行了2.03
代码链接在这: https://github.com/jiang42/AlgoContest/blob/master/uva/uva127.cpp
razrlele
2014-12-13 16:44:20 +08:00
@jiang42 。。。我最后AC的代码是0.8秒过的。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/153637

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX