【问题标题】:Stack around variable 'temp' is corrupted变量“temp”周围的堆栈已损坏
【发布时间】:2014-07-24 19:36:58
【问题描述】:

我正在尝试将包含由空格分隔的多个值的 std::string 转换为向量对象。我让它工作(意味着调试器在算法结束时在向量中显示正确的值),但是我遇到了一个我以前从未见过的异常​​。例外情况如下:

我以前从未见过这种情况,我已经研究了一个小时来研究导致这种情况的原因,但我仍然不明白。

导致异常的算法如下:

vector<BYTE> ConvertStringOfValuesToVectorOfBytes(std::string valStr)
{
    vector<string> vectorOfValues = split(valStr, ' '); //split string into vector of strings (works)
    vector<BYTE> Hex;
    vector<const char*> vectOfCStrings;

    for(int i = 0; i < vectorOfValues.size(); i++)
    {
        const char* temp = vectorOfValues[i].c_str();
        vectOfCStrings.push_back(temp);
    }

    //now we have a vector of c strings...

    for(int i = 0; i < vectOfCStrings.size(); i++)
    {       
        char temp = 0;
        sscanf(vectOfCStrings[i], "%x", &temp);
        Hex.push_back(temp);
    }

    return Hex;

} //<-- debugger gets to here and on the next step causes the exception

我不知道如何解决这个问题。正如我所说,算法在我得到正确结果的意义上“有效”,我只需要清除异常。我该如何解决这个问题?

【问题讨论】:

  • temp 设为整数?我不知道,只是刺伤。
  • 尝试使用 %c 扫描 char 而不是 %x 扫描 int。另外,不要在 C++ 中使用 sscanf。
  • 您似乎以某种方式溢出了 temp 值。 sscanf() 的用户输入应该是什么?

标签: c++ exception stack-corruption


【解决方案1】:

这行不对:

sscanf(vectOfCStrings[i], "%x", &temp);

%x 格式用于int,而不是char

因为sscanf 需要int 的地址,所以您会遇到堆栈损坏。它尝试使用您传递的地址作为能够持有int 的地址。它显然使用了比有效内存更多的内存。

你需要的是:

for(int i = 0; i < vectOfCStrings.size(); i++)
{       
    int temp = 0;
    sscanf(vectOfCStrings[i], "%x", &temp);
    Hex.push_back(static_cast<char>(temp));
}

【讨论】:

    【解决方案2】:
    std::vector<unsigned char> func(std::string valStr) {
        vector<string> vectorOfValues = split(valStr); //split string into vector of strings (works)
        vector<BYTE> Hex;
        vector<const char*> vectOfCStrings;
    
        for(int i = 0; i < vectorOfValues.size(); i++) {
            const char* temp = vectorOfValues[i].c_str();
            vectOfCStrings.push_back(temp);
        }
    
        //now we have a vector of c strings...
    
        for(int i = 0; i < vectOfCStrings.size(); i++) {
            int temp = 0;
            sscanf(vectOfCStrings[i], "%x", &temp);
            Hex.push_back(char(temp));
        }
    
        return Hex;
    }
    

    所以是的,我刚刚将第二个 tmp 设为 int,因为 sscanf 和类似的东西使用 int 作为类型,并且由于 byte 小于 int,这会导致您的溢出。

    不确定它是否有效,但它不再给我错误。

    【讨论】:

      【解决方案3】:

      罪魁祸首似乎在这两行:

          char temp = 0;
          sscanf(vectOfCStrings[i], "%x", &temp);
      

      这正是 C++ 中不使用 printf/scanf 系列函数并被std::iostream 机制取代的原因。当您指定 %x 时,函数 sscanf 期望获得指向 unsigned int 的指针,但您将指针传递给 char,而 sscanf 本身无法验证这一点。尽管一些现代编译器可以检查传递给 printfscanf 的值是否与格式说明符匹配并生成警告,否则通常不起作用(例如传递给函数的格式,而不是使用字符串文字)。所以这里 sscanf 取消引用指针 &temp 作为指向 unsigned int 的指针,并将临时变量周围的内存覆盖为 char == 1 的 sizeof。

      【讨论】:

        【解决方案4】:

        你的算法到底想完成什么?

        从外观上看,您正在将 std::string 分解为“单词”的 std::vector,然后将这些单词转换为 c 风格的字符串(为什么?),然后组装一个 std:vector 包含每个单词的第一个字母被解释为一个 int。使用 std:stringstream 代替:

        for ( auto& word : vectorOfValues )
        {
            for ( auto& letter : word ) 
            {
                unsigned int val;
                std::stringstream ss;
                ss << std::hex << word[0];
                ss >> val;
                Hex.push_back( static_cast<BYTE>( val ) );
            }
        }
        

        通常,如果您不直接与 C API 交互,则不应在 c++ 中使用 c 风格的字符串。

        【讨论】:

        • 我正在尝试将写入的十六进制值转换为实际的 BYTE 值。所以我不希望“0”转换为 48(0 的 ASCII 码),我希望“0”转换为 0x00
        • 那你不应该检查两个字符吗?否则你只会读取从 0x00 到 0x0F 的值?我认为如果你解释你想要完成的事情会更好。您为什么要尝试将 ascii 字符重新解释为 1 字节整数?
        猜你喜欢
        • 2018-03-12
        • 1970-01-01
        • 1970-01-01
        • 2021-03-28
        • 2012-11-08
        • 2019-09-04
        • 2020-07-26
        • 1970-01-01
        相关资源
        最近更新 更多