代码之家  ›  专栏  ›  技术社区  ›  PapaAtHome

VS2010,scanf,奇怪的行为

  •  0
  • PapaAtHome  · 技术社区  · 10 年前

    我正在将一些源代码从VC6转换为VS2010。代码是用C++/CLI编写的,它是一个MFC应用程序。它包括一行:

    BYTE mybyte;
    sscanf(source, "%x", &mybyte);
    

    这对于VC6来说很好(超过15年),但在VS2010中会出现问题,所以我创建了一些测试代码。

    void test_WORD_scanf()
    {
        char *source = "0xaa";
        char *format = "%x";
        int  result = 0;
    
        try
        {
            WORD pre    = -1;
            WORD target = -1;
            WORD post   = -1;
    
            printf("Test (pre scan):  stack: pre=%04x, target=%04x, post=%04x, sourse='%s', format='%s'\n", pre, target, post, source, format);
            result = sscanf(source, format, &target);
            printf("Test (post scan): stack: pre=%04x, target=%04x, post=%04x, sourse='%s', format='%s'\n", pre, target, post, source, format);
            printf("result=%x", result);
    
            // modification suggested by Werner Henze.
            printf("&pre=%x sizeof(pre)=%x, &target=%x, sizeof(target)=%x, &post=%x, sizeof(post)=%d\n", &pre, sizeof(pre), &target, sizeof(target), &post, sizeof(post));
        }
        catch (...)
        {
            printf("Exception: Bad luck!\n");
        }
    }
    

    构建这个(在调试模式下)是没有问题的。运行它会产生奇怪的结果,我无法解释。首先,我得到了两个printf状态的输出。然后是一个运行时警告,这对我来说是出乎意料的。

    Test (pre scan):  stack: pre=ffff, target=ffff, post=ffff, source='0xaa', format='%x'
    Test (post scan): stack: pre=ffff, target=00aa, post=ffff, source='0xaa', format='%x'
    result=1
    
    Run-Time Check Failure #2 - Stack around the variable 'target' was corrupted.
    

    使用调试器,我发现运行时检查失败是在从函数返回时触发的。有人知道运行时检查失败的原因吗?我用过谷歌,但找不到任何建议。

    在实际代码中,sscanf中使用的不是WORD,而是BYTE(我有一个BYTE版本的测试函数)。这导致了“%x”格式的实际堆栈损坏(用0覆盖变量pre),同时使用“%hx”(我希望是正确的格式)仍然会在覆盖变量prev的低位字节时造成一些问题。

    欢迎任何建议。

    注意:我编辑了示例代码以包含来自sscanf()的返回结果

    诚挚问候,

    安德烈·斯滕菲尔德。

    1 回复  |  直到 10 年前
        1
  •  0
  •   Werner Henze    10 年前

    sscanf 具有 %x writes an int 。如果您提供 BYTE WORD 然后会出现缓冲区溢出/堆栈覆盖。 %hx write a short int .

    解决方案是使用一个int变量 sscanf公司 写下来,然后设置 单词 字节 变量设置为读取值。

    int x;
    sscanf("%x", "0xaa", x);
    BYTE b = (BYTE)x;
    

    顺便说一句,为了你的测试和消息

    运行时检查失败#2-变量“target”周围的堆栈已损坏。

    您还应该打印出变量的地址,您可能会看到编译器在变量pre/target/post之间添加了一些填充/安全检查空间。