放置new能够承受优化,而不像memset一样吗?

7

我非常想知道它是否能够经受住GCC和clang采用的激进优化策略的考验。

考虑以下示例:

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

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

我能相信它来清除敏感数据吗?


2
你不能完全信任数组的放置方式 new at all! - Kerrek SB
我认为你不能信任自己编写的任何代码,你必须寻找编译器或操作系统提供的专门用于此目的的函数。 - Mark Ransom
2
一个用于此目的的操作系统函数可能会受到与memset相同的处理。不,它不能。这正是拥有这样的函数的关键所在。编译器无法证明副作用的缺失,因此无法删除它。 - Revolver_Ocelot
1
@bit2shift C++标准规定new(pointer) char[size]会写入size + y个字节,其中y是未指定的值。 - M.M
1
@bit2shift 是的,确实做了。 - M.M
显示剩余16条评论
2个回答

2

我不确定这是否是对你问题的回答,还是只是一些附加说明,但是你可以使用optimize()编译指令来禁用该特定函数的优化。

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

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

2
我认为在这里优化不会对你产生任何影响。标准要求在这种情况下进行值初始化:new(pointer) char[size]{},因此调用后,由pointer指向的内存将被填充为0。
如果您从未访问新指针或在访问之前覆盖它(基于可观察性),编译器可能会进行优化。如果您想避免这种微小的可能性,需要将指针定义为指向volatile

但是之后,缓冲区未被使用。 - Jarod42
@Jarod42,是的,我考虑过并更新了我的答案。 - SergeyA
在这两种情况下,我都使用这种方法,指针要么被返回(分配),要么被传递给一个释放函数,最终导致std::free - bit2shift
@Jarod42,我认为,在放置new之前将其转换为void*(以摆脱volatile)应该是可以的... 我想。 - SergeyA
3
优化器可以执行程序中没有可观察效果的任何操作。如果它能确定对象不会被使用,并且构造函数没有副作用,那么完全有权跳过构造函数。 - Mark Ransom
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接