为 std::shared_ptr 分配内存的正确方法

2024-03-04

我已经实现了一个功能,其中身份被赋予给我并且不受我的控制。它返回std::shared_ptr<const void>。在函数中,我分配任意数量的内存,并通过shared_ptr返回对它的访问。

我的内存分配完成了new unsigned char[123]。问题在于 valgrind 检测到 new 变体和删除变体的使用之间不匹配。当我使用new[](unsigned)为了分配内存,shared_ptr 析构函数使用delete(void*)解除分配它,每当您使用“不正确”的解除分配器进行分配时,valgrind 都会发出警告。

从更实际的角度来说,我编写了这个测试用例来展示我的意思:

TEST(Example, Test1)
{
  unsigned char* mem = new unsigned char[123];
  std::shared_ptr<const void> ptr(mem);
}

valgrind 报告称

==45794== Mismatched free() / delete / delete []
==45794==    at 0x4C2A64B: operator delete(void*) (vg_replace_malloc.c:576)
==45794==    by 0x40B7B5: _M_release (shared_ptr_base.h:150)
==45794==    by 0x40B7B5: ~__shared_count (shared_ptr_base.h:659)
==45794==    by 0x40B7B5: ~__shared_ptr (shared_ptr_base.h:925)
==45794==    by 0x40B7B5: ~shared_ptr (shared_ptr.h:93)
==45794==    by 0x40B7B5: Example_Test1_Test::TestBody() (test.cc:108)
==45794==  Address 0x5cb6290 is 0 bytes inside a block of size 123 alloc'd
==45794==    at 0x4C29CAF: operator new[](unsigned long) (vg_replace_malloc.c:423)
==45794==    by 0x40B72E: Example_Test1_Test::TestBody() (test.cc:107)

如果可能的话,我想避免使用 valgrind 过滤器。

分配任意数量的数据并作为返回的正确方法是什么std::shared_ptr<const void>?


如果你给shared_ptr<T> a T指针,它假设您创建了一个对象并暗示了删除器delete p;。如果您的分配实际上是使用 array-new 执行的,则需要传递一个适当的删除器来执行delete[] p;。您可以重复使用std::default_delete如果你喜欢:

return static_pointer_cast<const void>(
    std::shared_ptr<unsigned char>(
        new unsigned char[N],
        std::default_delete<unsigned char[]>()));

(您甚至不需要外部转换,因为转换是隐含的。)

在 C++17 中,shared_ptr支持数组,所以你可以说

shared_ptr<unsigned char[]>(new unsigned char[N])

在那里并获得正确的删除器(然后转换为 void)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为 std::shared_ptr 分配内存的正确方法 的相关文章

  • 锁定 ASP.NET 应用程序变量

    我在 ASP NET 应用程序中使用第三方 Web 服务 对第 3 方 Web 服务的调用必须同步 但 ASP NET 显然是多线程的 并且可能会发出多个页面请求 从而导致对第 3 方 Web 服务的同时调用 对 Web 服务的调用封装在自
  • 异常堆栈跟踪不显示抛出异常的位置

    通常 当我抛出异常 捕获它并打印出堆栈跟踪时 我会看到抛出异常的调用 导致该异常的调用 导致该异常的调用that 依此类推回到整个程序的根 现在它只向我显示异常所在的调用caught 而不是它所在的地方thrown 我不明白是什么改变导致了
  • 将设置函数(setter)标记为 constexpr 的目的是什么? [复制]

    这个问题在这里已经有答案了 我无法理解将 setter 函数标记为的目的constexpr 自 C 14 起这是允许的 我的误解来自以下情况 我使用 constexpr c tor 声明一个类 并且我将通过创建该类的 constexpr 实
  • C# 处理标准输入

    我目前正在尝试通过命令行断开与网络文件夹的连接 并使用以下代码 System Diagnostics Process process2 new System Diagnostics Process System Diagnostics Pr
  • C++ 将联合强制转换为其成员类型之一

    以下对我来说似乎完全符合逻辑 但不是有效的 C 联合不能隐式转换为其成员类型之一 有人知道为什么不这样做的充分理由吗 union u int i char c function f int i int main u v v i 6 f v
  • 带有运算符语法的错误消息,但不带有函数语法的错误消息

    为什么我在调用 unary 时收到错误消息 使用运算符语法 如果我用函数语法调用它就可以了 现场演示 https godbolt org z j7AbeQ template
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • 有什么方法可以重载 C# 中的扩展方法吗?

    我有以下模型模式 public abstract class PARENTCLASS public class CHILD A CLASS PARENTCLASS public static class EXTENSION public s
  • 如何合并非常大的 numpy 数组?

    我会有很多Numpy https docs scipy org doc numpy 1 14 0 reference arrays https docs scipy org doc numpy 1 14 0 reference arrays
  • 你好,我最近正在开发我的新游戏,我遇到了*无限跳跃*的问题

    所以基本上当我按跳跃 空格键时我会跳跃但是如果我连续按空格键它 只是跳啊跳啊跳等等 我不想要我只想它跳一次 code if Input GetKeyDown space isGrounded velocity y Mathf Sqrt ju
  • 子目录中的头文件(例如 gtk/gtk.h 与 gtk-2.0/gtk/gtk.h)

    我正在尝试使用 GTK 构建一个 hello world 其中包括以下行 include
  • 用于连接 DataTable 上的动态列的动态 LINQ

    我目前遇到的情况不确定如何继续 我有两个从数据库填充的数据表 我还有一个可用的列名称列表 可用于将这两个数据表连接在一起 我希望编写一组 LINQ 查询 这些查询将 显示两个数据表中的行 内部联接 用于从一个数据表更新另一个数据表 显示一个
  • Xamarin - SignalR 挂在连接上

    我正在尝试将我的 Xamarin 应用程序连接到托管在 Azure 上的 SignalR 后端 我遇到的问题是每次我在 HubConnection 上调用 StartAsync 时 它都会挂起客户端并且请求永远不会完成 我尝试通过应用程序进
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • 无法为 wsdl 文件创建服务引用

    I have wsdl文件和xsd我本地机器上的文件 我想在项目中添加服务引用 我没有网络服务 我只有wsdl file 我收到以下错误 The document was understood but it could not be pro
  • 使用 OleDbCommandBuilder 时访问 SQL 语法错误

    我要在 C 中使用 OleDbDataAdapter 在 Access 数据库中插入数据 但收到错误消息INSERT INTO 命令中的语法错误 BackgroundWorker worker new BackgroundWorker Ol
  • EnumDisplayDevices 与 WMI Win32_DesktopMonitor,如何检测活动监视器?

    对于我当前的 C 项目 我需要为在大量计算机上连接并处于活动状态的每个监视器检测一个唯一的字符串 研究指出了两种选择 使用 WMI 并查询 Win32 DesktopMonitor 以获取所有活动监视器 使用 PNPDeviceID 来唯一
  • 为什么 f(i = -1, i = -1) 是未定义的行为?

    我正在读关于违反评估顺序 http en cppreference com w cpp language eval order 他们举了一个令我困惑的例子 1 如果标量对象上的副作用相对于同一标量对象上的另一个副作用是无序的 则行为未定义
  • 无法在 C# 中为 EventArgs 分配使用派生类型的事件处理程序

    所以我有一个事件声明如下 public event EventHandler OnChangeDetected 然后我有以下处理程序被分配给该事件 myObject OnChangeDetected OnTableChanged 我的理解是
  • 如何在dll级别读取app.config? [复制]

    这个问题在这里已经有答案了 我在一个解决方案中有一个控制台应用程序项目和库项目 dll The 图书馆项目有 app config 文件 我在其中存储我在库中使用的一些键值对 控制台应用程序引用此 dll 我有另一个 app config

随机推荐