Jump to page: 1 2
Thread overview
A debug class has started
Dec 13, 2021
forkit
Dec 13, 2021
forkit
Dec 13, 2021
forkit
Dec 13, 2021
drug
Dec 13, 2021
ag0aep6g
Dec 13, 2021
drug
Dec 13, 2021
WebFreak001
Dec 13, 2021
forkit
Dec 13, 2021
H. S. Teoh
Dec 13, 2021
forkit
Dec 13, 2021
H. S. Teoh
Dec 13, 2021
forkit
Dec 13, 2021
H. S. Teoh
Dec 13, 2021
forkit
Dec 13, 2021
H. S. Teoh
Dec 14, 2021
WebFreak001
Dec 14, 2021
forkit
Dec 13, 2021
Stanislav Blinov
December 13, 2021
ok. one line in this code is causing a problem (as noted in comments)

an explanation as to the cause, is welcome ;-)


// ------------------------
module test;

import std : writeln, writefln;
import std.conv : to;

void main()
{
    string str = "abc;def;ab";
    char* w = cast(char*)str;
    writeln(replaceChar(w, str.length, ';', 'X'));
}

immutable(char)[] replaceChar(char* str, ulong len, char ch1, char ch2)
{
    for (ulong i = 0; i < len; i++)
    {
        if (str[i] == ch1)
        {
            writefln("Found %c at str[%d]", ch1, i); // fine

            // problem is with this next line:
            // the line works fine using DMD on windows - but crashes if using LDC on windows
            // On Linux, both DMD and LDC -> sigsegv
            //str[i] = ch2;
            // seems simple enough
            // - just replace the char currently in element str[i]) with 'X'
        }
    }
    return to!(immutable(char)[])(str);
}
// ------------------------
December 13, 2021
On Monday, 13 December 2021 at 09:49:05 UTC, forkit wrote:
>
> 
> 
oh...

Windows
 - dmd version is 2.098.0-dirty
 - ldc2 version is 1.28 (based on dmd v2.098.0)

Linux
 - dmd version is 2.098
 - ldc2 version is 1.20.1 (based on dmd v2.090.1)


December 13, 2021
On Monday, 13 December 2021 at 09:49:05 UTC, forkit wrote:
> ....

char* w = cast(char*)str.toStringz; // this seems to be the solution

class has ended ;-)
December 13, 2021
On 13.12.2021 13:49, forkit wrote:
> On Monday, 13 December 2021 at 09:49:05 UTC, forkit wrote:
>> ....
> 
> char* w = cast(char*)str.toStringz; // this seems to be the solution
> 
> class has ended ;-)

That's because `str` is initialized by a literal and you can not change it by definition. When you call `toStringz` it duplicates that literal (adding terminating zero at the end) and the duplicate is mutable. I would recommend do not use `toStringz` and just make duplicate of the literal - https://run.dlang.io/is/vaosW0
December 13, 2021
On 13.12.21 12:09, drug wrote:
> That's because `str` is initialized by a literal and you can not change it by definition. When you call `toStringz` it duplicates that literal (adding terminating zero at the end) and the duplicate is mutable. I would recommend do not use `toStringz` and just make duplicate of the literal - https://run.dlang.io/is/vaosW0

From the link:

> string str = "abc;def;ab".dup; // allocates the string in the heap
> char* w = cast(char*)str;
> writeln(replaceChar(w, str.length, ';', 'X'));

That still has undefined behavior. You cannot mutate the characters in a `string`. It doesn't matter if it came from a literal or `.dup`. Use `char[]` instead of `string`.
December 13, 2021
On 13.12.2021 14:26, ag0aep6g wrote:
> On 13.12.21 12:09, drug wrote:
>> That's because `str` is initialized by a literal and you can not change it by definition. When you call `toStringz` it duplicates that literal (adding terminating zero at the end) and the duplicate is mutable. I would recommend do not use `toStringz` and just make duplicate of the literal - https://run.dlang.io/is/vaosW0
> 
>  From the link:
> 
>> string str = "abc;def;ab".dup; // allocates the string in the heap
>> char* w = cast(char*)str;
>> writeln(replaceChar(w, str.length, ';', 'X'));
> 
> That still has undefined behavior. You cannot mutate the characters in a `string`. It doesn't matter if it came from a literal or `.dup`. Use `char[]` instead of `string`.

You're right. I forget to change `string str` to `auto str` or `char[] str`.
December 13, 2021

On Monday, 13 December 2021 at 11:09:18 UTC, drug wrote:

>

On 13.12.2021 13:49, forkit wrote:

>

On Monday, 13 December 2021 at 09:49:05 UTC, forkit wrote:

>

....

char* w = cast(char*)str.toStringz; // this seems to be the solution

class has ended ;-)

That's because str is initialized by a literal and you can not change it by definition. When you call toStringz it duplicates that literal (adding terminating zero at the end) and the duplicate is mutable. I would recommend do not use toStringz and just make duplicate of the literal - https://run.dlang.io/is/vaosW0

important: toStringz may do a copy with the current implementation but nothing in the docs states it actually does so. In fact there is commented out code where it in the past just dereferenced the memory after the string and checked if it was 0.

You should really use .dup if you want to mutate your string. (You would need to duplicate anyway if you don't want an unsafe cast)

pro-tip for bugs like this: just slap @safe: at the start of every file, the compiler will tell you everything that is risky and the bug will 9/10 times just sort itself out by fixing what the compiler complains about. (just recently helped someone with this again, was a 3 minute fix for a big code-base where manually searching the issue would have taken much longer)

December 13, 2021
On Monday, 13 December 2021 at 12:06:53 UTC, WebFreak001 wrote:
>
> You should really use `.dup` if you want to mutate your string. (You would need to duplicate anyway if you don't want an unsafe cast)

(this produces an unpredictable result??)
char* w = cast(char*)str.dup;

(but this seems to work - as expected)
char* w = strdup(cast(char*)str); // import core.stdc.string : strdup;

> pro-tip for bugs like this: just slap `@safe:` at the start of every file, the compiler will tell you everything that is risky

I like this idea. Thanks ;-)

December 13, 2021
On Mon, Dec 13, 2021 at 08:04:24PM +0000, forkit via Digitalmars-d-learn wrote:
> On Monday, 13 December 2021 at 12:06:53 UTC, WebFreak001 wrote:
> > 
> > You should really use `.dup` if you want to mutate your string. (You would need to duplicate anyway if you don't want an unsafe cast)
> 
> (this produces an unpredictable result??)
> char* w = cast(char*)str.dup;

Shouldn't you be using:

	char* w = str.dup.ptr;

instead??


T

-- 
It is impossible to make anything foolproof because fools are so ingenious. -- Sammy
December 13, 2021
On Monday, 13 December 2021 at 20:28:26 UTC, H. S. Teoh wrote:
> On Mon, Dec 13, 2021 at 08:04:24PM +0000, forkit via Digitalmars-d-learn wrote:
>> On Monday, 13 December 2021 at 12:06:53 UTC, WebFreak001 wrote:
>> > 
>> > You should really use `.dup` if you want to mutate your string. (You would need to duplicate anyway if you don't want an unsafe cast)
>> 
>> (this produces an unpredictable result??)
>> char* w = cast(char*)str.dup;
>
> Shouldn't you be using:
>
> 	char* w = str.dup.ptr;
>
> instead??
>
>
> T

that also produces the same unpredictable result.

i.e (an extra character from 'somewhere' appears in the output from line below)
writeln(replaceChar(w, str.length, ';', 'X'));


« First   ‹ Prev
1 2