在我们的C++代码中,我们有自己的string类(由于遗留原因)。它支持与std::string
非常相似的方法c_str()
。我注意到的是,许多开发人员没有正确地使用它。我已经将问题简化为以下几行:
const char* x = std::string("abc").c_str();
这段看似无害的代码相当危险,因为在调用c_str()
之后,std::string
上的析构函数会立即被调用。因此,您持有指向释放的内存位置的指针。
下面是另一个示例:
std::string x("abc");
const char* y = x.substr(0,1).c_str();
在这里,我们也使用指向释放位置的指针。
在测试期间不容易发现这些问题,因为内存位置仍然包含有效数据(尽管内存位置本身是无效的)。
我想知道你是否有任何建议,关于我如何修改类/方法定义,使开发人员永远不会犯这样的错误。
发布于 2014-05-27 08:45:38
代码的现代部分不应该像那样处理原始指针。仅当向采用const char*
的遗留函数提供参数时才调用c_str
。像这样:
legacy_print(x.substr(0,1).c_str())
为什么要创建const char*
类型的局部变量?即使你写了一个复制版的c_str_copy()
,你也会感到更头疼,因为现在客户端代码负责删除结果指针。
如果您需要将数据保留较长时间(例如,因为您希望将数据传递给多个遗留函数),则只需始终将数据包装在string实例中即可。
发布于 2014-05-27 15:08:57
最简单的解决方案是将析构函数更改为在销毁时在字符串的开头写入null。(或者,使用错误消息或0填充整个字符串;您可以使用一个标志对发布代码禁用此功能。)
虽然它不能直接防止程序员犯下使用无效指针的错误,但当代码没有做它应该做的事情时,它肯定会引起人们对问题的注意。这应该可以帮助您解决代码中的问题。
(正如您所提到的,此时错误不会被注意到,因为在大多数情况下,代码将愉快地使用无效内存运行。)
发布于 2014-05-27 09:53:04
考虑使用Valgrind或电动栅栏来测试您的代码。这两种工具中的任何一种都应该可以很容易地立即发现这些错误。
https://stackoverflow.com/questions/23879348
复制相似问题