【问题标题】:Can placement new survive optimization, unlike memset?与 memset 不同,placement new 能否存活优化?
【发布时间】:2016-06-25 16:02:25
【问题描述】:

所以我真的很想知道它能否在 GCC 和 clang 采用的激进优化策略中幸存下来。

考虑以下示例:

void* clean(void* pointer, std::size_t size) noexcept
{
    return new(pointer) char[size]{};
}

void doStuff()
{
    //...
    clean(pointer, size);
    //...
}

我可以信任它清理敏感数据的任务吗?

【问题讨论】:

  • 你不能信任数组放置 new at all!
  • @KerrekSB 该问题中指定的示例不是基本类型。如果我没记错的话,其中提到的“y”是给定类型所需的对齐方式。
  • "用于此目的的操作系统功能可能会受到与 memset 相同的处理" 不,不能。这正是具有这种功能的意义所在。编译器无法删除它,因为它不能证明没有副作用。
  • @bit2shift C++ 标准说new(pointer) char[size] 写入size + y 字节,其中y 是一个未指定的值
  • @bit2shift 是的,确实

标签: c++ memory optimization


【解决方案1】:

我不认为优化可以在这里对你耍任何花招。在这种情况下,标准要求值初始化:new(pointer) char[size]{},因此在此调用之后,pointer 指向的内存将被填充为 0。

如果您从不访问新指针或在访问之前覆盖它(基于可观察性),编译器可能会对其进行优化。如果您想避免这种轻微的可能性,您需要将您的指针定义为指向volatile 的指针。

【讨论】:

  • 但是之后,缓冲区没有使用。
  • @Jarod42,是的,我考虑了一下并更新了我的答案。
  • 在这两种情况下,我都使用这种方法,指针要么被返回(分配),要么被传递给导致std::free的释放函数。
  • @Jarod42,我认为,在放置新的(以消除易失性)之前强制转换为 void* 就可以了....我认为。
  • 允许优化器做任何对程序没有明显影响的事情。如果它可以确定对象不会被使用,并且构造函数没有副作用,那么完全跳过构造函数是完全可以的。
【解决方案2】:

我不确定这是对您问题的回答还是只是附注,但您可以使用 optimize() 编译器指令禁用对该特定功能的优化

void* __attribute__((optimize("O0"))) clean(void* pointer, std::size_t size) {
    // unmodifiable compiler code
}

这将确保您的 clean() 函数不会被优化掉

【讨论】:

    猜你喜欢
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 2017-09-16
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多