Jump to page: 1 27  
Page
Thread overview
A strange div bug on Linux x86_64, (both dmd & ldc2): long -5000 / size_t 2 = 9223372036854773308
Aug 13
mw
Not a bug! :)
Not a compiler bug.
Aug 13
mw
Aug 13
mw
Aug 13
bachmeier
Aug 13
mw
Aug 17
mw
Aug 13
bachmeier
Aug 13
jmh530
Aug 13
bachmeier
Aug 13
jmh530
Aug 13
matheus
Aug 13
mw
Aug 13
jmh530
Aug 13
mw
Aug 13
mw
Aug 13
Tove
Aug 13
mw
Aug 13
mw
Aug 13
mw
Aug 14
mw
Aug 14
mw
Aug 14
mw
Aug 14
mw
Aug 14
mw
Aug 13
mw
Aug 14
mw
Aug 14
claptrap
Aug 14
Avrina
Aug 20
mw
Aug 13
Avrina
Aug 13
jmh530
August 13
I post here because I think this bug's impact maybe pretty wide, it's a div bug  on Linux x86_64, (both dmd & ldc2).  I'm interested in knowing what caused this bug.

On Windows, I only tested dmd.exe, it correctly outputs -2500.


size_t: because I was taking array length, maybe many people do that too.


https://issues.dlang.org/show_bug.cgi?id=21151

import std.stdio;

void main() {
  long   a = -5000;
  size_t b = 2;
  long   c = a / b;
  writeln(c);
}


$ dmd divbug.d
$ ./divbug
9223372036854773308


$ ldc2 divbug.d
$ ./divbug
9223372036854773308


x86_64 x86_64 x86_64 GNU/Linux

$ dmd --version
DMD64 D Compiler v2.092.0

$ ldc2 --version
LDC - the LLVM D compiler (1.21.0):
  based on DMD v2.091.1 and LLVM 10.0.0
  built with LDC - the LLVM D compiler (1.21.0)
  Default target: x86_64-unknown-linux-gnu
  Host CPU: bdver2

August 13
On Thursday, 13 August 2020 at 07:22:18 UTC, mw wrote:
> I post here because I think this bug's impact maybe pretty wide, it's a div bug  on Linux x86_64, (both dmd & ldc2).  I'm interested in knowing what caused this bug.
>
> On Windows, I only tested dmd.exe, it correctly outputs -2500.
>
>
> size_t: because I was taking array length, maybe many people do that too.
>
>
> https://issues.dlang.org/show_bug.cgi?id=21151
>
> import std.stdio;
>
> void main() {
>   long   a = -5000;
>   size_t b = 2;
>   long   c = a / b;
>   writeln(c);
> }
>
>
> $ dmd divbug.d
> $ ./divbug
> 9223372036854773308
>
>
> $ ldc2 divbug.d
> $ ./divbug
> 9223372036854773308
>
>
> x86_64 x86_64 x86_64 GNU/Linux
>
> $ dmd --version
> DMD64 D Compiler v2.092.0
>
> $ ldc2 --version
> LDC - the LLVM D compiler (1.21.0):
>   based on DMD v2.091.1 and LLVM 10.0.0
>   built with LDC - the LLVM D compiler (1.21.0)
>   Default target: x86_64-unknown-linux-gnu
>   Host CPU: bdver2

"Not a bug." Or rather, same semantics as in C. The division reinterprets a as unsigned, and the result is within the positive range of a long, so it stays positive post-division.

#include <stdio.h>
void main() {
  long long int a = -5000;
  long long unsigned int b = 2;
  // the expression is unsigned, and reinterpreted as positive signed with the assignment
  long long int c = a / b;
  printf("%lli\n", c); // crazy number
}

August 13
On Thursday, 13 August 2020 at 07:22:18 UTC, mw wrote:
> I post here because I think this bug's impact maybe pretty wide, it's a div bug  on Linux x86_64, (both dmd & ldc2).  I'm interested in knowing what caused this bug.
>
> On Windows, I only tested dmd.exe, it correctly outputs -2500.
>
>
> size_t: because I was taking array length, maybe many people do that too.
>
>
> https://issues.dlang.org/show_bug.cgi?id=21151
>
> import std.stdio;
>
> void main() {
>   long   a = -5000;
>   size_t b = 2;
>   long   c = a / b;
>   writeln(c);
> }
>
>
> $ dmd divbug.d
> $ ./divbug
> 9223372036854773308
>
>
> $ ldc2 divbug.d
> $ ./divbug
> 9223372036854773308
>
>
> x86_64 x86_64 x86_64 GNU/Linux
>
> $ dmd --version
> DMD64 D Compiler v2.092.0
>
> $ ldc2 --version
> LDC - the LLVM D compiler (1.21.0):
>   based on DMD v2.091.1 and LLVM 10.0.0
>   built with LDC - the LLVM D compiler (1.21.0)
>   Default target: x86_64-unknown-linux-gnu
>   Host CPU: bdver2

"Not a bug." Or rather, same semantics as in C. The division reinterprets a as unsigned, and the result is within the positive range of a long, so it stays positive post-division.

#include <stdio.h>
void main() {
  long long int a = -5000;
  long long unsigned int b = 2;
  // the expression is unsigned, and reinterpreted as positive signed with the assignment
  long long int c = a / b;
  printf("%lli\n", c); // crazy number
}

Whether that is correct is a whole other question. Personally I think it's insane.
August 13
On Thursday, 13 August 2020 at 07:51:06 UTC, FeepingCreature wrote:
> "Not a bug." Or rather, same semantics as in C. The division reinterprets a as unsigned, and the result is within the positive range of a long, so it stays positive post-division.


https://issues.dlang.org/show_bug.cgi?id=21151

Let me add all my post together:

It can NOT silently do this, at least a warning.

BTW, on Windows, dmd correctly output -2500.

Just because C/C++ did it doesn't means it's correct.

And D supposed to be an improvement of C++.


OK, let me write this in this way to show it's impact:
==================================
import std.algorithm;
import std.stdio;

void main() {
  long[] a = [-5000, 0];
  long   c = sum(a) / a.length;
  writeln(c);
}
==================================


$ ./divbug
9223372036854773308
August 13
On Thursday, 13 August 2020 at 07:56:31 UTC, mw wrote:
> On Thursday, 13 August 2020 at 07:51:06 UTC, FeepingCreature wrote:
>> "Not a bug." Or rather, same semantics as in C. The division reinterprets a as unsigned, and the result is within the positive range of a long, so it stays positive post-division.
>
>
> https://issues.dlang.org/show_bug.cgi?id=21151
>
> Let me add all my post together:
>
> It can NOT silently do this, at least a warning.
>
> BTW, on Windows, dmd correctly output -2500.
>
> Just because C/C++ did it doesn't means it's correct.
>
> And D supposed to be an improvement of C++.
>
>
> OK, let me write this in this way to show it's impact:
> ==================================
> import std.algorithm;
> import std.stdio;
>
> void main() {
>   long[] a = [-5000, 0];
>   long   c = sum(a) / a.length;
>   writeln(c);
> }
> ==================================
>
>
> $ ./divbug
> 9223372036854773308

The windows version is probably different because you are building a 32 bit exe and therefore size_t is uint, which will be promoted to long in the division.

If you do a bit of a search on the forums you'll find this issue having come up many times before and you might find those discussions informative.
August 13
On Thursday, 13 August 2020 at 07:56:31 UTC, mw wrote:
> On Thursday, 13 August 2020 at 07:51:06 UTC, FeepingCreature wrote:
>> "Not a bug." Or rather, same semantics as in C. The division reinterprets a as unsigned, and the result is within the positive range of a long, so it stays positive post-division.
>
>
> https://issues.dlang.org/show_bug.cgi?id=21151
>
> Let me add all my post together:
>
> It can NOT silently do this, at least a warning.
>
> BTW, on Windows, dmd correctly output -2500.
>
> Just because C/C++ did it doesn't means it's correct.
>
> And D supposed to be an improvement of C++.
>
>
> OK, let me write this in this way to show it's impact:
> ==================================
> import std.algorithm;
> import std.stdio;
>
> void main() {
>   long[] a = [-5000, 0];
>   long   c = sum(a) / a.length;
>   writeln(c);
> }
> ==================================
>
>
> $ ./divbug
> 9223372036854773308

Yes, hence: not a compiler bug, but a spec bug. Implicit conversions should never throw away data, and silently converting from signed to unsigned, especially for a sign-sensitive operation like division, is insane. I'm not saying it's not an issue, I'm saying it should be raised against the spec, not the compiler, which faithfully implements it.
August 13
On Thursday, 13 August 2020 at 08:07:56 UTC, John Colvin wrote:
> The windows version is probably different because you are building a 32 bit exe and therefore size_t is uint, which will be promoted to long in the division.

$ /mnt/c/project/dmd2/windows/bin64/dmd.exe --version
DMD64 D Compiler v2.092.0-dirty
Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved written by Walter Bright


> If you do a bit of a search on the forums you'll find this issue having come up many times before and you might find those discussions informative.

Sigh, if D continue behave like this, it can hardly be called a C++ improvement.


August 13
On Thursday, 13 August 2020 at 08:23:30 UTC, mw wrote:
> On Thursday, 13 August 2020 at 08:07:56 UTC, John Colvin wrote:
>> The windows version is probably different because you are building a 32 bit exe and therefore size_t is uint, which will be promoted to long in the division.
>
> $ /mnt/c/project/dmd2/windows/bin64/dmd.exe --version
> DMD64 D Compiler v2.092.0-dirty
> Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved written by Walter Bright
>

compiler architecture doesn't imply generated code architecture. E.g. try compiling your file with -m32 or -m64 or -m32mscoff (see https://dlang.org/dmd-windows.html#switch-m32)

>> If you do a bit of a search on the forums you'll find this issue having come up many times before and you might find those discussions informative.
>
> Sigh, if D continue behave like this, it can hardly be called a C++ improvement.

D has many differences with C/C++, many of which I would consider an improvement. However, it does not address all of the things that cause difficulty with C/C++.

Personally I would love to be able to disallow implicit signed-to-unsigned conversions in almost all cases, but that would be a big breaking change.
August 13
On Thursday, 13 August 2020 at 09:25:07 UTC, John Colvin wrote:

> Personally I would love to be able to disallow implicit signed-to-unsigned conversions in almost all cases, but that would be a big breaking change.

This was broken without even an announcement or discussion (maybe I missed it):

foreach(int ii, val; [1, 2, 3, 4, 5]) {}

Upon compilation, you get a message

Deprecation: foreach: loop index implicitly converted from size_t to int

I had to go back and fix lots of previously working code, even though there was no reason at all that it would ever fail to work correctly. Then there is the move to safe by default. Surely if we can make those changes, we can change the behavior in this case. The output of this program is a serious WTF:

import std;
void main()
{
    foreach(int ii, val; [1, 2, 3, 4, 5]) {
        writeln(ii);
    }
    writeln(-5000/[1, 2, 3, 4].length);
}
August 13
On Thu, Aug 13, 2020 at 07:22:18AM +0000, mw via Digitalmars-d wrote: [...]
> void main() {
>   long   a = -5000;
>   size_t b = 2;
>   long   c = a / b;
>   writeln(c);
> }

You're mixing signed and unsigned values. That's generally dangerous territory where integer promotion rules inherited from C/C++ take over and cause sometimes weird effects, like here. Changing integer promotion rules will probably never happen now, because it will cause massive *silent* breakage of existing code. So, in the spirit of defensive programming, I recommend avoiding mixing signed/unsigned values in this way.


T

-- 
It said to install Windows 2000 or better, so I installed Linux instead.
« First   ‹ Prev
1 2 3 4 5 6 7