www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Segfault when writing to module-scope dynamic array

reply rombankzero <bogomancer gmail.com> writes:
Hi! Can anybody explain why this snippet segfaults when I try to 
run it:

 char[] array = new char[5];

 void main()
 {
     array[0] = 'a';
 }
It works fine if I move the array into main, or (strangely) if I change its type to ubyte[] instead of char[], or if I merely read the array without modifying it. I assumed it would heap-allocate a mutable dynamic array before main runs, but maybe I've misunderstood what `new` expressions do at module scope? Or is this some special case for char arrays (strings)? I really don't know what to make of it.
Nov 18 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 18 November 2019 at 12:31:10 UTC, rombankzero wrote:
 char[] array = new char[5];
It is almost always wrong to new things at module, class, or struct scope, since this create it in the static data segment. My guess is the compiler is seeing a static string and incorrectly putting it in the read-only segment with the other strings, and then writing to it thus triggers that segfault. just a guess, and if correct, this is a dmd bug. But I'd still recommend doing the `new` inside a function/module constructor anyway. That takes the static aspect out entirely and prevents some surprising bugs (right now the new is run at CTFE, not a huge deal here but with like classes it surprises a lot of people as the default pointer is shared between instances!)
 I assumed it would heap-allocate a mutable dynamic array before 
 main runs
but yeah this is NOT what it does. It runs new at *compile time* which means that `array` variable is pointing to static memory, it is not heap allocated at all.
Nov 18 2019
parent reply rombankzero <bogomancer gmail.com> writes:
On Monday, 18 November 2019 at 12:42:26 UTC, Adam D. Ruppe wrote:
 My guess is the compiler is seeing a static string and 
 incorrectly putting it in the read-only segment with the other 
 strings, and then writing to it thus triggers that segfault.
Yeah, that appears to be what's happening. For the record, I tried it on both Linux and Windows, and only got a segfault on Linux. And the fact that the ubyte[] case works only added to the confusion. On Monday, 18 November 2019 at 12:42:26 UTC, Adam D. Ruppe wrote:
 but yeah this is NOT what it does. It runs new at *compile 
 time* which means that `array` variable is pointing to static 
 memory, it is not heap allocated at all.
Are there cases where this behavior is useful? Because it seems pretty surprising to me. Like, when I see the "new" keyword, I immediately think "heap allocation", not anything being put into the data segment.
Nov 18 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 18 November 2019 at 13:22:20 UTC, rombankzero wrote:
 Yeah, that appears to be what's happening. For the record, I 
 tried it on both Linux and Windows, and only got a segfault on 
 Linux.
Yeah, that's consistent with other strings too. (The D type system calls both immutable, but the OS is looser on Windows. at least 32 bit.)
 Are there cases where this behavior is useful?
Yeah, it is cool for sentinel objects and default settings. Usually best when coupled with immutable to prevent more confusion but mutable versions sometimes make sense too. But it is rare and if you aren't specifically looking for it knowing the details, it isn't right. And since the syntax looks so normal it trips up a LOT of people. I think the compiler should probably start to error on it, and if you know what you're doing, maybe mark it special somehow. idk.
Nov 18 2019
parent rombankzero <bogomancer gmail.com> writes:
On Monday, 18 November 2019 at 13:28:26 UTC, Adam D. Ruppe wrote:
 But it is rare and if you aren't specifically looking for it 
 knowing the details, it isn't right. And since the syntax looks 
 so normal it trips up a LOT of people.

 I think the compiler should probably start to error on it, and 
 if you know what you're doing, maybe mark it special somehow. 
 idk.
Well, my fingers are singed. I'll know not to do that again, for what it's worth :)
Nov 18 2019