V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
razrlele
V2EX  ›  问与答

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

  •  
  •   razrlele · 2014-12-13 13:22:04 +08:00 · 2596 次点击
    这是一个创建于 3632 天前的主题,其中的信息可能已经有所发展或是发生改变。
    昨天在写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友可以帮忙看看, 谢谢!
    第 1 条附言  ·  2014-12-13 15:02:20 +08:00
    突然发现是自己犯了一个非常低级的错误。。。

    明明是需要储存两个字符的字符数组我却只分配了两个单位, 完全没有考虑‘\0’君的感受, 然后应该就是strcpy君找不到'\0'君引发的一系列字节混乱,然后就波及到了i君。。。
    17 条回复    2014-12-13 16:44:20 +08:00
    xdeng
        1
    xdeng  
       2014-12-13 13:29:13 +08:00 via iPhone   ❤️ 1
    字节对齐 或者这个数的附近变量溢出了
    razrlele
        2
    razrlele  
    OP
       2014-12-13 13:34:17 +08:00
    @xdeng ....那平时应该怎么注意防范啊...
    aaaa007cn
        3
    aaaa007cn  
       2014-12-13 14:02:35 +08:00
    > strcpy(tmpb, top(pb));
    strcpy 是一直复制到 \0 为止
    看看 top(pb) 返回的是什么,它的 \0 到哪里为止?

    > 另外问题就好像出现在strcpy上面, 把strcpy换成了自己构造的函数过后i值就没有出现异样.
    你自己构造的长什么样
    fliar
        4
    fliar  
       2014-12-13 14:10:25 +08:00 via iPad   ❤️ 1
    你的char数组都很短,string是以/0结尾,scanf应该不会检查越界,尝试从这边下手
    razrlele
        5
    razrlele  
    OP
       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
        6
    aaaa007cn  
       2014-12-13 14:17:23 +08:00
    那就是 strcpy 越界了啊
    因为它要一直拷贝到 top(pb) 的 \0 为止
    你这里可以 memcpy(tmpb, top(pb), 2);

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

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

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

    话说混起来用的话在工程项目中会出现什么问题么?
    tomriddle
        11
    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
        12
    razrlele  
    OP
       2014-12-13 15:22:30 +08:00
    @tomriddle 我用STL的stack超时了。。。

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

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

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

    你AC的代码运行时间是多少?
    jiang42
        16
    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
        17
    razrlele  
    OP
       2014-12-13 16:44:20 +08:00 via Android
    @jiang42 。。。我最后AC的代码是0.8秒过的。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   918 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 20:33 · PVG 04:33 · LAX 12:33 · JFK 15:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.