我尝试将十六进制编码的字符串转换为包含已解码字符串的const char *缓冲区。
为此,我有一个函数(string hex_decode(string hex_input)
),它接受字符串并对其进行解码
在自己多次测试功能后,我尝试了以下调用:
const char* hex_decoded_c_str = hex_decode(input).c_str();
看到它完全乱七八糟! 为了调试这个问题,我把它分成了两个语句,如:
string hex_decoded_string = hex_decode(input);
const char* hex_decoded_c_str = hex_decoded_string.c_str();
这次它完美无缺! 我很困惑,有谁知道什么会导致这样的事情?
答案 0 :(得分:1)
string
返回一个临时的c_str()
对象。 string
返回指向该字符串对象的私有部分的指针。一旦临时死亡(在完整表达式结束时),该指针指向无法访问的内存。这称为未定义的行为。
要解决此问题,请将返回值复制到本地const string&
对象中,或通过将其绑定到c_str()
引用来延长临时值的生命周期。 {{1}}的返回值的有效性与调用它的对象的生命周期有关。编译器,库或运行时无法强制执行。这是开发人员需要确保的事情。
供参考,请参阅Lifetime。
答案 1 :(得分:1)
string hex_decode(string hex_input)
的原型说hex_decode
总是返回一个新的字符串对象。
标准的第12.2#3
段说:
临时对象被作为评估全表达式的最后一步而被销毁,该表达式(词法上)包含创建它们的点。
此外c_str()
返回指向字符串对象内内容的指针。
在阅读c_str()
和data()
(现在执行相同功能)的文档时,您可以从此行中推断出该文档(请参阅here或21.4.7.1#1
):
每个c_str() + i == &operator[](i)
i in [0, size()]
。
因此:
c_str()
结束;
后,hex_decode()
返回的临时字符串必须被销毁。在破坏期间,它释放了底层字符数组。
但是为了保留字符数组,不需要复制临时字符串。 12.2#4,5
:
有两种情况下,临时表在与完整表达结束时不同的点被销毁。 ......第二个上下文是指引用绑定到临时引用。
因此,您只需将const引用绑定到临时对象并保存在复制构造函数调用中:
const string & hex_decoded_string = hex_decode(input);
const char* hex_decoded_c_str = hex_decoded_string.c_str();
答案 2 :(得分:0)
与
const char* hex_decoded_c_str = hex_decode(input).c_str();
您正在引用string
临时对象的内部表示(返回值),这在hex_decode(input)
超出范围时无效,紧接在{{1}之后调用。
使用另一种方法,您可以复制c_str()
对象,使该引用在您的范围内有效。
答案 3 :(得分:-1)
c_str()
实例被销毁后,std::string
方法返回的指针变为无效。