Visual c++ 加密++;SHA1函数
我无法找出我的函数有什么问题-它在返回时会导致断点Visual c++ 加密++;SHA1函数,visual-c++,crypto++,Visual C++,Crypto++,我无法找出我的函数有什么问题-它在返回时会导致断点 std::string generateHash(std::string source) { CryptoPP::SHA1 hash; byte digest[CryptoPP::SHA1::DIGESTSIZE]; hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size()); std::string output; C
std::string generateHash(std::string source)
{
CryptoPP::SHA1 hash;
byte digest[CryptoPP::SHA1::DIGESTSIZE];
hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size());
std::string output;
CryptoPP::HexEncoder encoder;
CryptoPP::StringSink test = CryptoPP::StringSink(output);
encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));
encoder.Put(digest, sizeof(digest));
encoder.MessageEnd();
return output; // here
}
encoder.Attach((CryptoPP::BufferedTransformation*)和CryptoPP::StringSink(输出))代码>
在这一行中,CryptoPP::StringSink(输出)
是一个临时对象。在此调用之后,CryptoPP::StringSink(输出)
不再存在。因此,如果您尝试跟随它的地址(encoder.Attach
和encoder.Put
),您将得到未定义的行为。(就像您永远不应该返回局部变量的地址一样)
我的参考代码:
std::string generateHash(std::string source)
{
CryptoPP::SHA1 hash;
byte digest[CryptoPP::SHA1::DIGESTSIZE];
hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size());
std::string output;
CryptoPP::HexEncoder encoder;
CryptoPP::StringSink test = CryptoPP::StringSink(output);
encoder.Attach(new CryptoPP::StringSink(output));
encoder.Put(digest, sizeof(digest));
encoder.MessageEnd();
return output;
}
Onemouth的解决方案是正确的,但以下是您遇到问题的原因:
StringSink(输出)
是堆栈上的临时文件,当StringSink
析构函数运行时,它将被清除
HexEncoder
拥有指向StringSink(输出)
的指针,因此HexEncoder
将在StringSink(输出)
因此,StringSink
被清理两次
为完整起见,StringSink
不会删除字符串output
,因为它采用的是引用,而不是指针
这是以下文件中记录的行为:
虽然这是非常不寻常的,但您可能能够按照以下方式执行您正在尝试执行的操作并修复它(但我不建议您以这种方式执行):
重定向器
停止所有权链。当重定向程序
被销毁时,它不会销毁其附加的转换(即StringSink
)。但是,这不是使用图书馆的方式
Redirector
s在库中的其他位置很有用,但在这种情况下并非如此
CryptoPP::HexEncoder encoder;
CryptoPP::StringSink test = CryptoPP::StringSink(output);
encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));
88 *** Important Usage Notes ***
89
90 1. If a constructor for A takes a pointer to an object B (except primitive
91 types such as int and char), then A owns B and will delete B at A's
92 destruction. If a constructor for A takes a reference to an object B,
93 then the caller retains ownership of B and should not destroy it until
94 A no longer needs it.
encoder.Attach(new Redirector(&CryptoPP::StringSink(output)));