Hi,
I wrote some test code to learn how to use the net module:
import net
var sock = newSocket()
sock.connect("myserver", port=net.Port(23))
var data: string
sock.readLine(data)
echo(data)
This compiles fine (on a Windows machine, using the compiler that comes witht he Windows nim installer):
E:\Nim-devel\play>nim c --threads:on -d:useSysAssert -d:useGcAssert connect.nim
Hint: used config file 'E:\Nim\config\nim.cfg' [Conf]
Hint: system [Processing]
Hint: connect [Processing]
Hint: net [Processing]
Hint: rawsockets [Processing]
Hint: unsigned [Processing]
Hint: os [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: times [Processing]
Hint: winlean [Processing]
connect.nim(5, 0) Warning: not GC-safe: 'sock' [GcUnsafe]
connect.nim(8, 0) Warning: not GC-safe: 'sock' [GcUnsafe]
connect.nim(8, 14) Warning: not GC-safe: 'data' [GcUnsafe]
CC: compiler_connect
[Linking]
Hint: operation successful (17103 lines compiled; 0.983 sec total; 18.184MB) [SuccessX]
However, when I run it I get a crash with the following error message:
E:\Nim-devel\play>connect
Traceback (most recent call last)
connect.nim(8) connect
net.nim(752) readLine
SIGSEGV: Illegal storage access. (Try to compile with -d:useSysAssert -d:useGcAssert for details.)
As you can see I already added the suggested compiler switches but I get the same error and the same information.
What am I doing wrong?
You need to initialize data before using it.
import net
var sock = newSocket()
sock.connect("myserver", port=net.Port(23))
var data = ""
sock.readLine(data)
echo(data)
You need to initialize data before using it.
Not really easy to remember that. :-(
I think this error is very easy to make! I'm a bit surprised that it is so easy to get such a crash with nim, particularly when using nim's standard library. The documentation does not say anything about this which makes it even more surprising.
I believe that Varriount's suggestion to add not nil annotations where necessary is very good.
@Araq, I had to look up the meaning of "pathos", so thank you, I learned a new word today :-D
Now that I know what pathos means I can say that I did not intend to "appeal to the emotions of the audience". Perhaps the "!" that I used may seem over-dramatic? It not my intention in any case. I was truly surprised that passing a nil string to a stdlib function can cause a crash. I do think that is an error that is easy to make (in fact you seem to agree since you said that newbies tend to get this wrong). I am surprised that the compiler does not warn about this. I went through the whole manual and several tutorials a while ago and I do not remember reading about this particular detail, but I surely missed it.
In any case, as you said, once you know about it the issue is easy to avoid.
May I ask in which cases would it make sense to leave a string uninitialized?
It's nice that you get a traceback here (unlike C where I'd be left banging my head on the wall).
It's exceptionally nice that this is deterministic! I did not know it was.
However, it would be even nicer if the runtime error message was better - even if it just said something like 'write to uninitialized string "result"'. Is that possible?
It seems 'not nil' will catch many of these at compile time? But even then some will slip through and better runtime errors will help.