2017-03-03 76 views
0

我试图将一个十六进制编码的字符串转换成一个包含解码字符串的const char *缓冲区。 为此,我有一个函数(string hex_decode(string hex_input))接受字符串并对其进行解码。
自行测试功能几次后,我尝试了以下调用:C++:嵌套时,两个单独的函数返回不同的结果吗?

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

@Biffen不再。 –

+0

我敢肯定,你在hex_decode中创建了一个本地字符串对象。由于string类具有深度复制赋值运算符,因此当您返回字符串时,它将被复制到hex_decoded_string对象中,而不会出现内存问题。在前一种情况下,您正在将hex_decoded_c_str指向堆栈内存,这是不正确的情况 –

回答

0

const char* hex_decoded_c_str = hex_decode(input).c_str(); 

你正在做一个参照string临时对象(返回值),这是无效的内部表示,当hex_decode(input)超出范围,则c_str()电话之后。

用另一种方法,您复制string对象,使该引用在您的范围内有效。

+0

*“临时对象[...],它在下一行中无效。”* - 这是不准确的。作为评估包含创建点的完整表达式的最后一步,临时对象被销毁。如果在完整表达式后面的同一行上有代码,则临时文件已经在同一行上死了**。最好不要使用*“行”*的概念,这对C++编译器来说是毫无意义的。 – IInspectable

+0

*“指令”*不是在C++中使用的术语。它通常归因于汇编编程。仍然不准确是不准确的改进。 – IInspectable

+0

好的,目前的措辞对你更好吗? –

-1

c_str()方法返回的指针在std::string实例被销毁后变为无效。

1

string hex_decode(string hex_input)返回临时对象stringc_str()将一个指针返回到该字符串对象的私有部分。一旦临时死亡(在完整表达式的末尾),该指针指向无法访问的内存。这就是所谓的未定义的行为

要解决此问题,请将返回值复制到本地string对象中,或者通过将其绑定到const string&引用来延长临时对象的生存期。返回值c_str()的有效性与其被调用对象的生命周期相关。遵守不能由编译器,库或运行时强制执行。这是开发者需要确定的事情。

仅供参考,请参阅Lifetime

1

原型string hex_decode(string hex_input)表示一个新的字符串对象总是由hex_decode返回。标准的

段落12.2#3说:

临时对象被销毁作为评价全表达式(词法)包含了他们所创建点的最后一步。

此外c_str()返回一个指向内的字符串对象东西

当读取文档c_str()data()(现在执行同样的功能),你可以推断,从该线(见here21.4.7.1#1):

c_str() + i == &operator[](i)为每i in [0, size()]

因此:

一旦c_str()结束还有;hex_decode()返回的临时字符串必须被销毁。在销毁期间,它释放底层字符数组。

但是,为了保留字符数组,不需要复制临时字符串。 12.2#4,5

有两种情况,临时状态在与完整表达式结尾不同的点处销毁。 ...第二个上下文是当引用绑定到临时的时候。

所以你可以绑定一个常量引用到临时对象,并节省拷贝构造函数调用:

const string & hex_decoded_string = hex_decode(input); 
const char* hex_decoded_c_str = hex_decoded_string.c_str();