rsp*_*984 7 c++ memory buffer strict-aliasing type-punning
我正在努力实现共享内存缓冲区而不破坏C99的严格别名规则.
假设我有一些处理一些数据的代码,需要有一些'临时'内存来运行.我可以把它写成:
void foo(... some arguments here ...) {
int* scratchMem = new int[1000]; // Allocate.
// Do stuff...
delete[] scratchMem; // Free.
}
Run Code Online (Sandbox Code Playgroud)
然后我有另一个功能,做一些其他需要一个临时缓冲区的东西:
void bar(...arguments...) {
float* scratchMem = new float[1000]; // Allocate.
// Do other stuff...
delete[] scratchMem; // Free.
}
Run Code Online (Sandbox Code Playgroud)
问题是在操作期间可能会多次调用foo()和bar(),并且在性能和内存碎片方面,整个地方的堆分配可能非常糟糕.一个明显的解决方案是分配一个适当大小的公共共享内存缓冲区,然后将其作为参数传递给foo()和bar(),BYOB样式:
void foo(void* scratchMem);
void bar(void* scratchMem);
int main() {
const int iAmBigEnough = 5000;
int* scratchMem = new int[iAmBigEnough];
foo(scratchMem);
bar(scratchMem);
delete[] scratchMem;
return 0;
}
void foo(void* scratchMem) {
int* smem = (int*)scratchMem;
// Dereferencing smem will break strict-aliasing rules!
// ...
}
void bar(void* scratchMem) {
float* smem = (float*)scratchMem;
// Dereferencing smem will break strict-aliasing rules!
// ...
}
Run Code Online (Sandbox Code Playgroud)
我想我现在有两个问题:
- 如何实现一个不违反别名规则的共享公共暂存内存缓冲区?
- 即使上面的代码确实违反了严格的别名规则,别名也没有"伤害".因此,任何理智的编译器都可以生成(优化的)代码,但仍会让我遇到麻烦吗?
谢谢
将对象解释为字节序列始终是有效的(即,将任何对象指针视为指向字符数组的第一个元素的指针,这不是别名冲突),并且您可以在任何字节序列中构造对象。足够大且适当对齐的内存。
因此,您可以分配一个大的 s 数组char(任何符号),并找到对齐的偏移量alignof(maxalign_t);现在,一旦您构造了适当的对象(例如,在 C++ 中使用placement-new),您就可以将该指针解释为对象指针。
当然,您必须确保不要写入现有对象的内存;事实上,对象的生命周期与代表该对象的内存发生的情况密切相关。
例子:
char buf[50000];
int main()
{
uintptr_t n = reinterpret_cast<uintptr_t>(buf);
uintptr_t e = reinterpret_cast<uintptr_t>(buf + sizeof buf);
while (n % alignof(maxalign_t) != 0) { ++n; }
assert(e > n + sizeof(T));
T * p = :: new (reinterpret_cast<void*>(n)) T(1, false, 'x');
// ...
p->~T();
}
Run Code Online (Sandbox Code Playgroud)
malloc请注意,由或获得的内存始终new char[N]对齐为最大对齐(但不能更多,并且您可能希望使用过度对齐的地址)。
| 归档时间: |
|
| 查看次数: |
1700 次 |
| 最近记录: |