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 scope
和return ref
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现