相关疑难解决方法(0)

这是严格的别名违规吗?任何类型指针都可以作为字符指针的别名吗?

我仍在努力理解严格别名允许和不允许的内容。这个具体的例子是否违反了严格的别名规则?如果不是,为什么?是因为我将新的不同类型放入 char* 缓冲区吗?

template <typename T>
struct Foo
{
    struct ControlBlock { unsigned long long numReferences; };
    Foo()
    {
        char* buffer = new char[sizeof(T) + sizeof(ControlBlock)];
        // Construct control block
        new (buffer) ControlBlock{};
        // Construct the T after the control block
        this->ptr = buffer + sizeof(ControlBlock);
        new (this->ptr) T{};
    }
    char* ptr;

    T* get() { 
        // Here I cast the char* to T*.
        // Is this OK because T* can alias char* or because
        // I placement newed a T …
Run Code Online (Sandbox Code Playgroud)

c++ strict

7
推荐指数
2
解决办法
216
查看次数

malloc-free-malloc和严格别名

我最近一直试图理解严格别名的一个特定方面,我想我已经制作了尽可能小的有趣代码.(对我来说很有趣,就是!)

更新:根据目前为止的答案,很明显我需要澄清这个问题.从某个角度来看,这里的第一个列表是"明显"定义的行为.真正的问题是遵循这个逻辑到自定义分配器和自定义内存池.如果我malloc在开始时有一大块内存,然后编写我自己的my_malloc并且my_free使用那个单个大块,那么UB是不是因为它不使用官方free

我会坚持使用C,有点随意.我得到的印象是更容易谈论,C标准更清晰一点.

int main() {
    uint32_t *p32 = malloc(4);
    *p32 = 0;
    free(p32);

    uint16_t *p16 = malloc(4);
    p16[0] = 7;
    p16[1] = 7;
    free(p16);
}
Run Code Online (Sandbox Code Playgroud)

第二个可能malloc会返回与第一个相同的地址malloc(因为它free介于两者之间).这意味着它正在访问具有两种不同类型的相同内存,这违反了严格的别名.那么上面肯定是未定义的行为(UB)?

(为简单起见,让我们假设malloc总是成功.我可以添加检查返回值malloc,但这会使问题混乱)

如果不是UB,为什么?标准中是否有明确的例外,它说mallocfree(和calloc/ realloc/ ...)被允许"删除"与特定地址相关的类型,允许进一步访问在地址上"压印"一个新类型?

如果malloc/ free是特殊的,那么这是否意味着我不能合法地编写我自己的克隆行为的分配器malloc?我确信有很多项目都有自定义分配器 - 它们都是UB吗?

自定义分配器

因此,如果我们决定必须定义这样的自定义分配器行为,则意味着严格别名规则本质上是"不正确的".我会更新它,说只要你不再使用类型的指针,就可以通过不同('new')类型的指针写入(不读取).如果确认所有编译器基本上都遵守了这个新规则,那么这个措辞可能会悄然改变.

我得到的印象是,gcc并且clang基本上尊重我的(积极的)重新解释.如果是这样,也许应该相应地编辑标准?关于 …

c strict-aliasing

5
推荐指数
2
解决办法
657
查看次数

标签 统计

c ×1

c++ ×1

strict ×1

strict-aliasing ×1