D域推导把域引用搞成域中了.

地址

// dmd -dip1000
@safe:
struct Correct {
    private int* ptr;
    int* get() return { return ptr; }
}

struct Faulty(T) {
    private T* ptr;
    T* get() return { return ptr; }
}

struct Workaround(T) {
    private T* ptr;
    T* get() return {
        return *&ptr; // *&绕过
    }
}

// 失败(应)
unittest {
    int* outlive;
    Correct c;
    outlive = c.get(); // error
}

// 编译(不应该)
unittest {
    int* outlive;
    Faulty!int f;
    outlive = f.get(); // 应为错
}

// 失败(应该)
unittest {
    int* outlive;
    Workaround!int w;
    outlive = w.get(); // error
}

1ag0aep6g:
真的可这样返回有问题指针吗?事实上,测试用例只返回null.
似乎无属性推断,DMD假设get可能返回有问题的指针.但属性推断,DMD查看实际返回表达式.
StanislavBlinov:
当然可以.ptr指向及值来源,与该测试用例无关,因此省略.
ag0aep6g:
请举例.尝试返回有问题指针时,DMD显示与"正确"情况下相同错误.
StanislavBlinov:
在构造器中分配它,析构器中释放它,禁用复制和赋值.
ag0aep6g:
我想到DIP1000时,容易想到栈指针.但是,是的也应该允许malloc/free.
完整示例:

import core.stdc.stdlib: free, malloc;
struct Faulty
{
    private int* ptr;
    this(int v) @trusted
    {
        ptr = cast(int*) malloc(int.sizeof);
        *ptr = v;
    }
    ~this() @trusted { if (ptr !is null) free(ptr); }
    @disable this(this);
    @disable void opAssign(Faulty);
    int* get1() @safe return { return ptr; }
    int* get2()() @safe return { return ptr; }
}
void main() @safe
{
    int* outlive;
    {
        auto f1 = Faulty(42);
        outlive = f1.get1(); /* 错误 */
        outlive = f1.get2(); /* 应为错*/
    }
    /* `outlive`在此无效 */
}

推断该方法为"中域".奇怪的是,用pragma(msg,...)打印时没显示.

有了该信息,可构建即使无malloc/free@trusted也能显示内存破坏的测试用例:

struct Faulty
{
    private int x;
    private int* unused;
    int* get1() @safe return scope { return &x; }
}
int* f(int x) @safe
{
    auto f = Faulty(x);
    return f.get1(); /*返回栈指针*/
}
void main() @safe
{
    int* p1 = f(42);
    int* p2 = f(13);
    import std.stdio;
    writeln(*p1); /* 打印"13".错误. */
}

Dennis:
域推断转换返回引用为返回域,编译器内部混淆了return scopereturn ref.

posted @   zjh6  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示