www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - NullPointerError signals are useful and here is why we should have

reply Hipreme <msnmancini hotmail.com> writes:
I was developing a game within my engine, and I've stumbled in 
some problems out there with null pointers.

Imagine this simple program:

```d

class Test
{
     void doIt(){}
}
void main()
{
     Test t;
     t.doIt();
}
```

It compiles and then it kills with signal 11 when using DMD on 
linux.
If we were using Java, this program would not even build, because 
it would fail stating that it was never initialized.
But I don't really care about analyzers, I would rather have a 
runtime error or exception showing where and when it had this 
invalid value.

So, the main thing about this, is that I don't know how many 
people developed using DLLs in D, but its experience is far from 
ideal, put together to classes and hot reloading and things can 
go worse than expected.


Whenever my program crashes without messages, I simply go to 
Visual Studio and open my exe and try to run it again. This time 
I've done the same thing, and it wasn't able to find anything on 
the program, instead, it got a completely random and misleading 
error message.

![The procedure entry point _d-arraycatT could not be located in 
the dynamic link library 
G:\HipremeEngine\projects\letter_rain\letter_rain_hiptemp.dll](https://i.ibb.co/Mf09jSK/err.png)

Try to understand what is the problem in that code? Yes, exactly, 
it is a null pointer.

And yes, in this case it is fairly simple, but I was in the 
middle of a refactor, and instead of using arrays, I went into 
using pools:

So, reduced, check this code:

```d
class MainScene : AScene, IHipPreloadable
{
	mixin Preload;

	Strip[] stripList;
	
	/** Constructor */
	override void initialize()
	{
		foreach(i; 0..30)
		{
                     import hip.math.random;
                     Strip s = new Strip();
		    stripList~= s;
                     s.pos.x = Random.range(0, 800);
		}
	}
}
```

After some refactor, I got this code:


```d
class MainScene : AScene, IHipPreloadable
{
	mixin Preload;

	Pool!Strip stripList;
	
	/** Constructor */
	override void initialize()
	{
		foreach(i; 0..30)
		{
			import hip.math.random;
			stripList.get().pos.x = Random.range(0, 800);
		}
	}
}
```


Now, the problem looks obvious! I need to initialize the pool 
instance with `new Pool!Strip()`. But while I was doing, it 
wasn't this obvious, and getting this error message (built with 
LDC), didn't help me solving my problem at all.


Beyond this simple problem, there is hot reloading there.

That means, whenever you save your code, the file is rebuilt and 
reloaded automatically, and the problem is that at least for me, 
I tend to keep saving and resaving many times, that means I 
create incomplete code there, and then it just crashes my main 
program because my code wasn't even complete. And currently, 
there's no obvious way how I could control for it to say "It's 
okay, simply unload the DLL".

Working with DLLs have been a pain for me since the beginning 
from how hard it was to find the correct flags, from how 
different it behaves per compiler, and from how incomplete the 
support is. I believe that requiring someone to fix DLL right now 
would simply have priority 0, so, here I stand making a request 
proposal that would benefit the entire language much beyond the 
current hot new subject.
Oct 23 2023
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
I use DLL and i do hotreload in my engine

I have a single file module that solve this: 
https://github.com/ryuukk/backtraced/

Works in both linux/windows


I setup my signal handler this way, very simple:

```D

version(DLL) export extern(C) void on_reload(State* state) {
     LINFO("reloaded");

     debug rt_register_crash_handler();
}

```

And this example code in the DLL:

```D
         int* test = null;
         *test = 5;
```


Will give me this:

```
-------------------------------------------------------------------+
Received signal 'exception' (3221225477ll)
-------------------------------------------------------------------+
C:\dev\kdom\projects\game\app.d:144 - game.app.on_tick
C:\dev\kdom\projects\game\app.d:144 - game.app.on_tick
C:\dev\kdom\projects\game\app.d:144 - rt_register_crash_handler
C:\dev\kdom\projects\game\app.d:144 - BaseThreadInitThunk
C:\dev\kdom\projects\game\app.d:144 - RtlUserThreadStart
make: *** [makefile:36: game-run] Error 2816
```

I now know where exactly the code failed and i can fix it

```D
version(DLL) export extern(C) void on_tick(State* state) {

     if (state.engine.input.is_key_just_pressed(Key.KEY_SPACE))
     {
         int* test = null;
         *test = 5;
     }
}
```



I think someone made a PR to have something similar already, but 
i forgot where (phobos or druntime)
Oct 23 2023
parent Hipreme <msnmancini hotmail.com> writes:
On Monday, 23 October 2023 at 20:53:04 UTC, ryuukk_ wrote:
 I use DLL and i do hotreload in my engine

 I have a single file module that solve this: 
 https://github.com/ryuukk/backtraced/

 [...]
Thanks a lot! I'll try to work with that and see how far I can reach with it :D
Oct 23 2023