2017-01-09 37 views
0

嗨腐败我工作的一个C++项目,我有一个问题。存储数据造成周围可变

下面是我的代码

tempfingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_TYPE_RSA); 
    char temp[48]; 
    memset(temp, 0, sizeof(temp)); 
    for (i = 0; i < 16; i++) 
    { 
     //fingerprintstream << (unsigned char)tempfingerprint[i] << ":"; 
     if (temp[0] == 0) 
     { 
      sprintf(temp, "%02X:", (unsigned char)tempfingerprint[i]); 
     } 
     else 
     { 
      //sprintf(temp, "%s:%02X", temp, (unsigned char)tempfingerprint[i]); 
      char characters[3]; 
      memset(characters, 0, sizeof(characters)); 
      //If less than 16, then add the colon (:) to the end otherwise don't bother as we're at the end of the fingerprint 
      sprintf(characters, "%02X:", (unsigned char)tempfingerprint[i]); 
      strcat(temp, characters); 
     } 
    } 
    //Remove the end colon as its not needed. 48 Will already be null terminated, so the previous will contain the last colon 
    temp[47] = 0; 
    return string(temp); 

当我运行我的应用程序,我从Visual Studio收到以下错误

Run-Time-Check Failure #2 - Stack around the variable 'temp' was corrupted. 

我已经通过Valgrind的和没有错误运行在Linux上相同的代码显示出来,所以我不确定Windows的问题是什么。

感谢您提供的任何帮助。

+4

*我通过Valgrind在Linux上运行相同的代码,并且没有显示任何错误,所以我不确定Windows的问题是什么。* - 这不是Windows的问题。为什么你使用字符数组,并希望它们足够大以容纳你放置在它们中的数据?看起来你在写'C'而不是'C++'。 – PaulMcKenzie

+3

'字符'看起来太短。 – user4581301

+2

如果您计算终止的nul字符,“%02X:”不会生成超过3个字符。 –

回答

3

这里有一个方法用在保罗麦肯齐在谈论基于它看起来像你试图用流做(尽管他可能有不同的实现它)

#include <iostream> 
#include <sstream> 
#include <iomanip> // output format modifiers 
using namespace std; 

int main() 
{ 
    stringstream fingerprintstream; 
    // set up the stream to print uppercase hex with 0 padding if required 
    fingerprintstream << hex << uppercase << setfill('0'); 

    // print out the first value without a ':' 
    fingerprintstream << setw(2) << 0; 

    for (int i = 1; i < 16; i++) // starting at 1 because first has already been handled. 
    { 
     // print out the rest prepending the ':' 
     fingerprintstream << ":" << setw(2) << i; 
    } 
    // print results 
    std::cout << fingerprintstream.str(); 
    return 0; 
} 

输出:

00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F 

刚刚意识到我认为OP与垃圾产出相冲突的原因。当您输出一个号码时,<<将使用适当的转换来获取文字,但是如果您输出的字符是<<则会打印字符。因此,fingerprintstream << (unsigned char)tempfingerprint[i];采用tempfingerprint[i]的二进制值,并感谢演员阵营,试图将其渲染为角色。而不是“97”,你会得到(假设ASCII)“a”。大量您尝试打印的内容将会产生无意义的字符。

示例:如果我改变

fingerprintstream << ":" << setw(2) << i; 

fingerprintstream << ":" << setw(2) << (unsigned char)i; 

输出变为

0?:0?:0?:0?:0?:0?:0?:0?:0?:0?:0 :0 
:0?:0?:0 
:0?:0? 

注意的标签和换行。

我需要知道的tempfingerprint定义可以肯定的,但你或许可以移除铸件解决垃圾输出问题。

根据新的信息,tempfingerprintconst char *,所以tempfingerprint[i]char并将被打印为字符。

我们想了许多,所以我们必须强制吸盘是一个整数。

static_cast<unsigned int>(tempfingerprint[i]&0xFF) 

&0xFF屏蔽了一切,但最后一个字节,消除负数的符号扩展到巨大的正数显示无符号的时候。

+0

谢谢,tempfingerprint是一个'const char *'。我尝试删除演员,所以它只是'fingerprintstream << std :: setw(2)<< tempfingerprint [i];'但我仍然得到胡言乱语 – Boardy

+0

@Boardy给我们'fingerprintstream'数据样本,作为“乱码”没有传达任何信息。 – PaulMcKenzie

+0

乱码是'00e0〜0 0x0 /0┌0ý0h0ñ0'我期待'11:65:7E:0A:94:55:88:77:EC:68:A4:0D:A9'作为例如(我已经截断了我期待的完整输出)。输出不完全相同,因为它有一些特殊字符,所以我可以发布一个屏幕截图,如果你愿意 – Boardy

0

有,据我看到的,在代码中的两个问题而导致超出数组边界:

首先,char temp[48]你确切地保留48个字符用于存储结果的;但是,当使用第16个值调用strcat(temp, characters),并且characters至少包括包含冒号的字符时,则temp将包括16 * 3个数字/冒号+一个终止的字符,即49个字符(不是48)。请注意,strcat会自动附加字符串终止字符。

其次,您定义了char characters[3],这样您可以保留两位数字和冒号的位置,但不能用于终止'\0'-字符。因此,sprintf(characters, "%02X:",...)将超过characters的数组边界,因为sprintf也附加字符串终止符。

因此,如果您不想一般地重写代码,将您的定义更改为char temp[49]char characters[4]将解决该问题。