import strutils proc testExcept() = try: var part = "1,2".split(',') echo part[0], part[1], part[3] # part[3] special for error except: echo getCurrentExceptionMsg() testExcept() and this test crashed with: 12SIGSEGV: Illegal storage access. (Attempt to read from nil?) How I can catch similar errors?
http://www.nimrod-code.org/nimrodc.html
Play with the compiler and see if you can get bounds checking while getting the performance you want!
But in the default release mode, there is no bounds checking - therefore you get a seg fault trying to access invalid memory; no exceptions are going to be thrown for you to catch.
I test above code in C# and Pascal ABC.net. Both of them raised exception in release mode.
From /Nimrod/lib/system/excpt.nim:
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} = template processSignal(s, action: expr) {.immediate.} = if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n") elif s == SIGSEGV: action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n") elif s == SIGABRT: when defined(endb): if dbgAborting: return # the debugger wants to abort action("SIGABRT: Abnormal termination.\n") elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n") elif s == SIGILL: action("SIGILL: Illegal operation.\n") elif s == SIGBUS: action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n") else: action("unknown signal\n") # print stack trace and quit when hasSomeStackTrace: GC_disable() var buf = newStringOfCap(2000) rawWriteStackTrace(buf) processSignal(sig, buf.add) # nice hu? currying a la nimrod :-) writeToStdErr(buf) GC_enable() else: var msg: cstring template asgn(y: expr) = msg = y processSignal(sig, asgn) writeToStdErr(msg) when defined(endb): dbgAborting = True quit(1) # always quit when SIGABRT I don't know all subtleties(nuances) nimrod language. Therefore I ask here. Whether there is a safe and fast way to change file excpt.nim for experiment, for example as: :: when defined(noSigAbort): raise newException(EOS, signalMessage) else: writeToStdErr(signalMessage) quit(1)
You really only have 2 plausible options here:
tl;dr SEGFAULTS == DEAD PROGRAM I'm sure there are some very specific cases that might warrant this behaviour, but I don't think this is one of those cases.
Not depending on bound checks is pretty strong opinion, Kenneth_Sills.
Just forget the "release mode" distinction.
Nimrod allows fine grained control whether you want Java/C#-like behaviour (ie babysitting regarding code safety) or whether you want raw-but-unsafe power on block-level, much like in pascal or ada.
dmitry, consult:
http://nimrod-code.org/manual.html#compilation-option-pragmas
Just invoke the compiler with --boundChecks:on --nilChecks:on (or use in-source pragmas if your IDE does not allow to control compiler).
Your code will obviously run slower (still, much faster than C#) , use profiler to identify criticical code paths and wrap them with:
{.push checks: off.}
code which must be fast
{.pop.}
That way, the impact of "managed" code is still small, but you get the benefit of catching and dealing with critical bugs at run time.
Finally, installing custom signal sigsegv handler is perfectly ok thing, regardless whether it's C or Nimrod - for example doing execl(argv[0], argv) is sometimes used as emergency recovery. Naturally, it's just Unix thing, on windows the equivalent of SIGSEGV/SIGBUS is SEH.