为什么此D程序会引发奇怪的访问冲突异常?

kbz*_*bie 2 d exception access-violation dmd visual-studio

每当运行以下程序时,它都会因这个奇怪的异常而崩溃:

“在dfun.exe中的0x00B31028处引发了异常:0xC0000005:访问冲突读取位置0x00000000。

我正在使用visuald和dmd在Visual Studio中进行编译。不确定是否要提供更多信息,请问...

module dfun;

import std.stdio;

class Event(Args...)
{
    private void function(Args)[] _funcArray;

    public this()
    {
    }

    public void addHandler(void function(Args) handler)
    {
        _funcArray.length++;
        _funcArray[$ - 1] = handler;
    }

    public void opCall(Args args)
    {
        foreach(func; _funcArray)
        {
            func(args);
        }
    }
}

void foo(int a, char c)
{
    writeln(a, c);
}

int main()
{
    Event!(int, char) doIt;
    doIt.addHandler(&foo);

    doIt(5, 'a');

    readln();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果将代码更改为此,具有相同的基本功能:

module dfun;

import std.stdio;

void foo(int a, char c)
{
    writeln(a, c);
}

int main()
{
      //Event!(int, char) doIt;
      //doIt.addHandler(&foo);

      void function(int, char)[] func;

      func.length++;

      func[0] = &foo;

      func[0](5, 'a');

      readln();
      return 0;
}
Run Code Online (Sandbox Code Playgroud)

它工作正常。班上休息什么?

小智 5

您不会在以下行上初始化事件:

Event!(int, char) doIt;
doIt.addHandler(&foo);
Run Code Online (Sandbox Code Playgroud)

类是引用类型,并且具有null其初始值(.init)。这意味着您将需要doIt显式初始化:

Event!(int, char) doIt = new Event!(int, char)();
Run Code Online (Sandbox Code Playgroud)

可以使用以下命令将其缩短一些auto

auto doIt = new Event!(int, char);
Run Code Online (Sandbox Code Playgroud)

那应该解决这个问题。这里的一个问题:是否Event需要成为一个类并具有引用语义,或者结构是否同样可以满足您的目的?如果可以使用结构,则无需对其进行初始化。

您的另一个小问题addHandler function:无需++length; arr[$-1]跳舞-D具有串联运算符〜

public void addHandler(void function(Args) handler)
{
    _funcArray ~= handler;
}
Run Code Online (Sandbox Code Playgroud)