Comment #0 by bearophile_hugs — 2011-05-07T06:06:11Z
This little program:
int foo(int x, int y) {
return x / y;
}
void main() {
foo(1, 0);
}
Produces the stack trace (dmd 2.053beta):
object.Error: Integer Divide by Zero
----------------
...\test.d(5): _Dmain
----------------
While this similar Python2 program:
def foo(x, y):
return x / y
def main():
foo(1, 0)
main()
Gives the stacktrace (feel fee to ignore the first global call to main()):
Traceback (most recent call last):
File "...\temp.py", line 5, in <module>
main()
File "...\temp.py", line 4, in main
foo(1, 0)
File "...\temp.py", line 2, in foo
return x / y
ZeroDivisionError: integer division or modulo by zero
[Idea1] On Python the stacktrace is reversed compared to the D one, maybe this is better.
[Idea2] And as first line it prints this, that's useful for D too:
Traceback (most recent call last):
[Idea3] And the Python stacktrace shows the line/function where the division by zero happens too, instead of just all the frames of the functions up to the one that has called the function that has generated the division by zero. I'd like to see foo() too in the D stacktrace.
------------------------------------
This program:
int foo(int x) {
if (x > 0)
return bar(x - 1);
else
return 10 / x;
}
int bar(int x) {
if (x > 0)
return foo(x - 1);
else
return 10 / x;
}
void main() {
foo(10);
}
dmd 2.053beta (witout -g switch) gives:
object.Error: Integer Divide by Zero
----------------
40CCF4
40CB6B
402041
402021
402041
402021
402041
402021
402041
402021
402041
402021
40205A
4025FB
4021F7
411FDD
----------------
[Idea4] When the -g switch is not used I suggest to add a note about missing debug info, useful for not expert programmers/newbies:
object.Error: Integer Divide by Zero
----------------
Traceback, no symbolic debug info (most recent call last):
40CCF4
40CB6B
402041
402021
402041
402021
402041
402021
402041
402021
402041
402021
40205A
4025FB
4021F7
411FDD
----------------
Instead of just:
object.Error: Integer Divide by Zero
----------------
Traceback (most recent call last):
40CCF4
40CB6B
402041
402021
402041
402021
402041
402021
402041
402021
402041
402021
40205A
4025FB
4021F7
411FDD
----------------
------------------------------------
This little program:
int foo(int x) {
if (x > 0)
return foo(x - 1);
else
return 10 / x;
}
void main() {
foo(10);
}
dmd 2.053beta gives just (here DMD has performed tail-call optimization, so there are no stack frames to show for the recursive calls to foo()):
object.Error: Integer Divide by Zero
----------------
...
----------------
A bigger similar example:
import core.stdc.stdio: printf;
nothrow pure int str2int(const char *str, in int n=0) {
if (str == null || *str == '\0') {
int x = 10 / cast(size_t)*str; // A bug
return n;
} else
return str2int(str+1, n*10 + *str-'0');
}
void main() {
printf("%d\n", str2int("12345678".ptr));
}
The asm shows that DMD performs the tail-call optimization on str2int():
_D5test37str2intFNaNbxPaxiZi comdat
push EBX
mov EBX,8[ESP]
test EBX,EBX
push ESI
mov ESI,EAX
push EDI
je L12
cmp byte ptr [EBX],0
jne L1A
L12: pop EDI
mov EAX,ESI
pop ESI
pop EBX
ret 4
L1A: lea EDX,1[EBX]
movzx ECX,byte ptr [EBX]
lea EDI,[ESI*4][ESI]
lea EDI,-030h[EDI*2][ECX]
mov ESI,EDI
mov EBX,EDX
test EDX,EDX
je L12
cmp byte ptr [EDX],0
je L12
jmp short L1A
object.Error: Integer Divide by Zero
----------------
...
----------------
[Idea5] In this case the stacktrace may add a note:
object.Error: Integer Divide by Zero
----------------
...\test.d(4): int test.str2int(const char*, const int) [Tail-Call Optimized]
----------------
--------------------------------------
This little program just crashes at runtime (dmd 2.053beta):
int foo() {
return foo();
}
void main() {
foo();
}
With DMD 2.052 it gives:
object.Error: Stack Overflow
------------------------------------
Comment #1 by bearophile_hugs — 2011-05-07T06:21:51Z
KennyTM~ reminds me that the [idea 3] is bugus, because divisions by zero are not DMD exceptions. So please ignore it.
Comment #2 by code — 2015-02-03T03:49:01Z
> [Idea1] On Python the stacktrace is reversed compared to the D one, maybe this is better.
Definitely better, important information is easier to find in the console.
Comment #3 by timothee.cour2 — 2016-03-21T07:22:04Z
debug info is broken with dmd:
eg last frame often skipped; line numbers often off by a few lines [plus or minus], debug info also gets broken with partial recompilation
with ldc these problems go away
Comment #4 by robert.schadek — 2024-12-07T13:31:27Z