d懒参数问题

原文
当前懒参数表明创建引用局部变量闭包.允许逃逸懒参数,而不在分配局部变量,会导致泄漏某个栈域指针内存错误.

extern(C) int printf(const char*,...) @safe;

auto foo(lazy double i) @safe
{
   return { return i; } ;
}

auto bar() @safe
{
   double i = 4.0;
   return foo(i);
}

void baz() @safe
{
   double[2] i = 3.14;
// 此值覆盖了4.0
// 用char[16] val = 'f'; 替代
// 可打印确定性垃圾
}

void main() @safe
{
   auto x = bar();
   baz();
   printf("%f\n", x()); 
}

打印了错误的3.14.潜在编译器可识别懒参数逃逸,并在堆上分配i=4.0,但因为是单独编译模型,不能通用解决,因此应该拒绝代码.

这是已知引用-引用错误的更复杂变体,包括返回出域的本地对象引用:

ref int foo(ref int i) { return i; }
ref int bar() { int val; return foo(i); }

这是简化版本,它更好地解释了原理,并演示了类似的问题(也打印垃圾):

import std.stdio;

alias long[10] T;

T delegate() dg;

void foo(ref T i) @safe
{
   dg = { return i; } ;
}

void bar() @safe
{
   T i = 1;
   foo(i);
}

void rewrite_stack() @safe
{
   T tmp = -1;
}

void main() 
{
   bar();
   rewrite_stack();
   writeln(dg());
}

另一个测试用例:

//test.d 
@safe:

auto toDg(E)(lazy E value)
{
    return { return value; };
}

C t;

class C
{
    auto getDg()
    {
        // return () => prop;
        return toDg(prop);
    }

    final @property string prop()
    {
        assert(this is t);
        return null;
    }
}

void smashStack() {
    int[1024] dummy = 0xcafebabe;
}


void main()
{
    t = new C();
    auto result = t.getDg();
    smashStack();
    result();
}

编译器要么拒绝代码(接受无效代码),要么生成闭包(错误码).
升级严重级,因为在@safe代码中,(根据是否覆盖栈)表现为潜在错误.
正是因为类问题,我有个dip来弃用参数,用闭包代替它们,所以该特殊问题可能不会得到解决.
同时,我建议用闭包替换lazy参数.

降级到闭包,所以降级正确的闭包类型并得到正确行为应该很容易,2022年有一个dconf在线讨论.

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