c++ - Google Sparsehash 在不可复制的类型上使用 realloc()
问题描述
考虑这个简单的程序:
#include <string>
#include <sparsehash/dense_hash_map>
int main()
{
google::dense_hash_map<std::string, int> map;
map["foo"] = 0;
}
使用 GCC 8.2 和-Wclass-memaccess
(或-Wall
)编译会产生警告:
sparsehash/internal/libc_allocator_with_realloc.h:68:40: warning:
‘void* realloc(void*, size_t)’ moving an object of non-trivially copyable type
‘struct std::pair<const std::__cxx11::basic_string<char>, int>’;
use ‘new’ and ‘delete’ instead [-Wclass-memaccess]
return static_cast<pointer>(realloc(p, n * sizeof(value_type)));
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
问题是:
- 它是未定义的行为吗?
- 您能否建议可以应用于应用程序代码的修复或解决方法(不是通过更改 Sparsehash 或避免使用它)?
- (奖励积分)你能构造一个实际上因此而行为不端的程序(使用 std::string 或你自己的非平凡类型)吗?到目前为止,我在使用 std::string 作为键类型的代码中没有看到任何问题,尽管 std::string 必须是非常常用的键类型。
我在这里提出了一个问题:https ://github.com/sparsehash/sparsehash/issues/149
解决方案
1. 它是未定义的行为吗? 是的。永远不要使用 realloc() 复制对象,因为有时它们具有指向资源的内部指针。当 2 个不同的对象运行其析构函数时,问题就会出现。现在,同一资源发生了双重释放,完全没有。
2. 您能否建议可以应用于应用程序代码的修复或解决方法(不是通过更改 Sparsehash 或避免使用它)?
尝试
#include <memory>
并换线
google::dense_hash_map<std::string, int> map;
至
google::dense_hash_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>, std::allocator> map;
现在,它不会使用谷歌的分配器libc_allocator_with_realloc
3.(加分)你能构造一个实际上因此而行为不端的程序(使用 std::string 或你自己的非平凡类型)吗?到目前为止,我在使用 std::string 作为键类型的代码中没有看到任何问题,尽管 std::string 必须是非常常用的键类型。
不容易。因为您正试图引起未定义的行为。在您的测试程序中,我将提供长度至少为 32 个字符的字符串,因此不会启动小字符串优化。并且可以在 gcc 的堆中进行一些测试以查看它是否已损坏。见 1
推荐阅读
- tailwind-css - TailwindCSS 使用带有占位符颜色的 @apply
- python-3.x - 可视化给定 numpy 数组的值分布
- python - GeoDjango 在模型中的模板表单上显示地图
- php - MTURK API:从 PHP 访问分配对象的私有字段?
- performance-testing - 将数据源用于加密密码的 Web 性能测试
- servicenow - 从服务门户小部件中访问 GlideRecord
- c# - 如何防止 TabControl 在按下 Button 时切换选项卡?
- spring-batch - 回滚 ItemProcessor 并仍然调用 ItemWriter
- android - 实现 Android Auto 语音命令支持
- gradle - While loop to monitor task in gradle