Jump to page: 1 2 3
Thread overview
ldc executable crashes with this code
Feb 02, 2022
forkit
Feb 02, 2022
H. S. Teoh
Feb 03, 2022
forkit
Feb 03, 2022
Basile B.
Feb 03, 2022
Basile B.
Feb 03, 2022
forkit
Feb 03, 2022
H. S. Teoh
Feb 03, 2022
forkit
Feb 03, 2022
H. S. Teoh
Feb 03, 2022
forkit
Feb 04, 2022
Patrick Schluter
Feb 04, 2022
forkit
Feb 04, 2022
forkit
Feb 04, 2022
Stanislav Blinov
Feb 04, 2022
H. S. Teoh
Feb 05, 2022
forkit
Feb 07, 2022
bauss
Feb 03, 2022
Tejas
Feb 03, 2022
Ali Çehreli
February 02, 2022
Any reason why compiling this with ldc would cause the exe to crash?

Compiling with DMD (using either declaration of palindrome works just fine though)


// ----

module test;

import std;

void main()
{
    char[] palindrome = cast(char[])"able was I ere I saw elba";

   //char[] palindrome = ['a','b','l','e','w','a','s','I','e','r','e','I','s','a','w','e','l','b','a'];

    writeln(palindrome);

    // note: The line below causes the exe to crash when compiled with ldc
    // but only if using the first version of palindrome.

    writeln(palindrome.reverse);
}

// ---
February 02, 2022
On Wed, Feb 02, 2022 at 11:21:52PM +0000, forkit via Digitalmars-d-learn wrote: [...]
>     char[] palindrome = cast(char[])"able was I ere I saw elba";

String literals are immutable by default. Casting immutable to mutable
is UB (Undefined Behaviour).


[...]
>     writeln(palindrome.reverse);

Especially because .reverse mutates its argument.  So you're attempting to overwrite immutable data here. That's probably what caused the crash: the literal is put in the read-only segment and the OS killed the program when it tried to write to data in that read-only segment.


T

-- 
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird. -- D. Knuth
February 03, 2022
On Wednesday, 2 February 2022 at 23:30:50 UTC, H. S. Teoh wrote:
> On Wed, Feb 02, 2022 at 11:21:52PM +0000, forkit via Digitalmars-d-learn wrote: [...]
>>     char[] palindrome = cast(char[])"able was I ere I saw elba";
>
> String literals are immutable by default. Casting immutable to mutable
> is UB (Undefined Behaviour).
>
>
> [...]
>>     writeln(palindrome.reverse);
>
> Especially because .reverse mutates its argument.  So you're attempting to overwrite immutable data here. That's probably what caused the crash: the literal is put in the read-only segment and the OS killed the program when it tried to write to data in that read-only segment.
>
>
> T

that explains ldc perhaps (although i don't really get it. It's cast to mutable and being assigned to mutable.

in any case... ldc doesn't like it, but dmd is fine with this ??

February 03, 2022

On Thursday, 3 February 2022 at 01:39:33 UTC, forkit wrote:

>

On Wednesday, 2 February 2022 at 23:30:50 UTC, H. S. Teoh wrote:

>

[...]

that explains ldc perhaps (although i don't really get it. It's cast to mutable and being assigned to mutable.

in any case... ldc doesn't like it, but dmd is fine with this ??

your cast from immutable to mutable is an undefined behavior, this may work or not.

>

Note that casting away a const qualifier and then mutating is undefined behavior, too, even when the referenced data is mutable. This is so that compilers and programmers can make assumptions based on const alone. For example, here it may be assumed that f does not alter x:

(from https://dlang.org/spec/const3.html#removing_with_cast)

February 03, 2022
On Thursday, 3 February 2022 at 01:39:33 UTC, forkit wrote:
>

oops!  forgot the .dup

char[] palindrome = cast(char[])"able was I ere I saw elba".dup;

;-)


February 03, 2022

On Thursday, 3 February 2022 at 01:51:34 UTC, Basile B. wrote:

>

On Thursday, 3 February 2022 at 01:39:33 UTC, forkit wrote:

>

On Wednesday, 2 February 2022 at 23:30:50 UTC, H. S. Teoh wrote:

>

[...]

that explains ldc perhaps (although i don't really get it. It's cast to mutable and being assigned to mutable.

in any case... ldc doesn't like it, but dmd is fine with this ??

your cast from immutable to mutable is an undefined behavior, this may work or not.

>

Note that casting away a const qualifier and then mutating is undefined behavior, too, even when the referenced data is mutable. This is so that compilers and programmers can make assumptions based on const alone. For example, here it may be assumed that f does not alter x:

(from https://dlang.org/spec/const3.html#removing_with_cast)

the D safe way :

void main() @safe
{
    char[] palindrome = "able was I ere I saw elba".dup;
    writeln(palindrome);
    writeln(palindrome.reverse);
}
February 02, 2022
On Thu, Feb 03, 2022 at 01:39:33AM +0000, forkit via Digitalmars-d-learn wrote:
> On Wednesday, 2 February 2022 at 23:30:50 UTC, H. S. Teoh wrote:
> > On Wed, Feb 02, 2022 at 11:21:52PM +0000, forkit via Digitalmars-d-learn wrote: [...]
> > >     char[] palindrome = cast(char[])"able was I ere I saw elba";
> > 
> > String literals are immutable by default. Casting immutable to
> > mutable is UB (Undefined Behaviour).
> > 
> > 
> > [...]
> > >     writeln(palindrome.reverse);
> > 
> > Especially because .reverse mutates its argument.  So you're attempting to overwrite immutable data here. That's probably what caused the crash: the literal is put in the read-only segment and the OS killed the program when it tried to write to data in that read-only segment.
[...]
> that explains ldc perhaps (although i don't really get it. It's cast to mutable and being assigned to mutable.

Assigning the literal to char[] simply creates a mutable slice of the immutable data. That's technically UB. Then .reverse modifies the array in-place, which means you violated immutable.


> in any case... ldc doesn't like it, but dmd is fine with this ??

UB doesn't mean a guaranteed crash, it means the result will be implementation-dependent (and likely not what was intended). It's possible that dmd didn't put the literal in a read-only segment, or there may be some other reason. In any case, just because it worked by chance does not mean it's OK to simply cast immutable to mutable and then proceed to mutate it.


T

-- 
Let X be the set not defined by this sentence...
February 03, 2022
On Thursday, 3 February 2022 at 01:57:12 UTC, H. S. Teoh wrote:
>

would be nice if the compiler told me something though :-(

i.e. "hey, dude, you really wanna to that?"

February 03, 2022

On Wednesday, 2 February 2022 at 23:21:52 UTC, forkit wrote:

>

Any reason why compiling this with ldc would cause the exe to crash?

Compiling with DMD (using either declaration of palindrome works just fine though)

// ----

module test;

import std;

void main()
{
char[] palindrome = cast(char[])"able was I ere I saw elba";

//char[] palindrome = ['a','b','l','e','w','a','s','I','e','r','e','I','s','a','w','e','l','b','a'];

writeln(palindrome);

// note: The line below causes the exe to crash when compiled with ldc
// but only if using the first version of palindrome.

writeln(palindrome.reverse);

}

// ---

This segfaults even on dmd 2.098.0 for me.
Clearly implementation defined behavior.

February 02, 2022
On Thu, Feb 03, 2022 at 02:01:34AM +0000, forkit via Digitalmars-d-learn wrote: [...]
> would be nice if the compiler told me something though :-(
> 
> i.e. "hey, dude, you really wanna to that?"

Mark your function @safe, and the compiler will stop you from unsafe casts of this nature. That's part of the reason we have @safe. ;-)


T

-- 
Everybody talks about it, but nobody does anything about it!  -- Mark Twain
« First   ‹ Prev
1 2 3