Why does this D program throw a strange access violation exception?

2

Whenever the following program is ran, it crashes with this strange exception:

"Exception thrown at 0x00B31028 in dfun.exe: 0xC0000005: Access violation reading location 0x00000000."

I'm compiling in visual studio with visuald and dmd. Not sure of any more information to give, ask away...

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;
}

But if the code is changed to this, with the same basic functionality:

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;
}

It works just fine. What does the class break?

visual-studio
exception
d
access-violation
dmd
asked on Stack Overflow Jun 11, 2019 by kbzombie

1 Answer

5

You're not initializing the event on these lines:

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

Classes are reference types, and have null as their initial value (.init). This means that you will need to initialize doItexplicitly:

Event!(int, char) doIt = new Event!(int, char)();

This can be made slightly shorter using auto:

auto doIt = new Event!(int, char);

That should take care of that problem. One question here: does Event need to be a class and have reference semantics, or would a struct work just as well for your purposes? If you could use a struct, there'd be no need to initialize it.

Another tiny nitpick is in your addHandler function: there's no need for the ++length; arr[$-1] dance - D has the concatenation operator ~:

public void addHandler(void function(Args) handler)
{
    _funcArray ~= handler;
}
answered on Stack Overflow Jun 11, 2019 by BioTronic

User contributions licensed under CC BY-SA 3.0