Segfault with std.container.Array but not regular dynamic array

Maxim Fomin maxim at maxim-fomin.ru
Wed Nov 28 05:43:03 PST 2012


On Wednesday, 28 November 2012 at 13:09:36 UTC, Dan wrote:
> On Monday, 26 November 2012 at 15:44:42 UTC, Joseph Rushton 
> Wakeling wrote:
>> Hello all,
>>
>> I'm writing some code which is meant to represent a network of 
>> linked nodes.
> [snip]
>
> Ok, another follow up. I can reproduce your segfault using your 
> posted code, it is included below. But the interesting thing 
> is, I was doing the "testing" out of your Network!Node2 in a 
> unittest section. By whittling down, the smallest crash case I 
> could come up with is this:
>
> import std.typecons;
> import std.stdio;
> alias RefCounted!(int) Foo;
> unittest {
>   Foo[int] map;
>   map[1] = Foo();
> }
>
> When I change that unittest block to a 'void main()' it works 
> just fine. I tried the same change of unittest to 'void main()' 
> on your code and found the same results - no crash. I think the 
> crash issue might not be with map (even though Maxim found some 
> troubling stuff with uninitialized structs being destructed 
> when inserting a key that is not present). Or maybe it is just 
> a map problem and by switching to main I am just getting lucky 
> in not getting a crash.
>

Actually bug is still there - changing unittest to main() does 
not fix program, even if it seems to run correctly. The problem 
with memory corruption is that it may happen with no observable 
segfaults just because erroneous operation was performed on 
memory which was permitted to be read/written.

Valgrind is tool which may show absence of memory corruption 
errors. Giving your example:

import std.typecons;
import std.stdio;
alias RefCounted!(int) Foo;

void main() { // main instead of unittest
   Foo[int] map;
   map[1] = Foo();
}

valgrind outputs:
==2562== Conditional jump or move depends on uninitialised 
value(s)
==2562==    at 0x41A424: 
_D3std8typecons18__T10RefCountedTiZ10RefCounted6__dtorMFZv
==2562==    by 0x41A4D5: 
_D3std8typecons18__T10RefCountedTiZ10RefCounted8opAssignMFS3std8typecons18__T10RefCountedTiZ10RefCountedZv
==2562==    by 0x41A238: _Dmain
==2562==    by 0x41C42B: 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi7runMainMFZv
==2562==    by 0x41BCCD: 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi7tryExecMFMDFZvZv
==2562==    by 0x41C472: 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi6runAllMFZv
==2562==    by 0x41BCCD: 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi7tryExecMFMDFZvZv
==2562==    by 0x41BC89: _d_run_main
==2562==    by 0x41BACA: main

which is exactly the same problem with unittest version: 
uninitialized object and bogus this pointer - now "this" just 
points to some allocated memory. Probably this happens because 
between running unittest and main function druntime has allocated 
more memory - and more memory is valid to be read.

Actually, I have also found this and considered to be not 
significant (bug still exists) and thus have not reported - next 
time I will be more verbose.


More information about the Digitalmars-d-learn mailing list