Help us understand the problem. What is going on with this article?

safe functionは未定義動作を許さないといったな、あれは嘘だ (タイトルは釣りです)

More than 1 year has passed since last update.

遅くなりましたすいません, これはD言語アドベントカレンダーの23日目の記事です.
この記事はほんとにチラシの裏であり得られるものなどなにひとつないのでポエムのつもりでごらんください.

D言語の言語仕様にはsafe functionというものがあります.

2018年12月27日時点の https://dlang.org/spec/function.html#function-safety の記述において, safe function の定義は

Safe functions are functions that are statically checked to exhibit no possibility of undefined behavior.
Undefined behavior is often used as a vector for malicious attacks.

となっています. ひらたくいうとsafe functionは未定義動作を踏まないことを保証してくれるそうです.

safe functionを定義するためには @safe という属性を関数に付与してやる必要があります.

以下のコードは @safe ではコンパイルできません.

void func() @safe
{
    const x = 1;
    auto y = &x; // cannot take address of local `x` in `@safe` function.
}

safe function 内で許可されない操作は https://dlang.org/spec/function.html#safe-functions に一覧があります.
上の例だと No taking the address of a local variable or function parameters に抵触しているためコンパイルエラーとなります.

さて, このリストをみると未初期化変数の扱いに関する記述がないことに気がつきます.
実際に @safe 内で未初期化変数を使うコードを書いてみると, コンパイル・実行ともに可能でランダムな値が取得できます.

int func() @safe
{
    int x = void;
    return x;
}

この挙動にすでにきづいた人がいて, チケットをすでにあげていました. https://issues.dlang.org/show_bug.cgi?id=18016
そしてどうやら議論の中で
「ポインタの未初期化変数は未定義動作として扱う(つまりsafe function内で記述することを許容しない)けど, 値の未初期化変数は implementation defined と定義して未定義動作から外すわ. 仕様もそういう感じに変更しとく」
などと, implementation defined なる概念になりました. (なので別にsafe functionは未定義動作を許容するようになったわけではないのです)

個人的にはこれを未定義動作ではないというのはちょっと無理があるかなとは思いますが, いろいろ考えてみても特に不便もないので別にいいかなという感想です.

まあこのコードがコンパイルエラーになるだけC言語よりはるかにマシでしょ, D言語使おう.

void func() @safe
{
    int* x = void;
}
kubo39
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away