cristicbz/scid — Issue #76: Ref Counting Bug
Author: dsimcha
Created: 2011-12-19 01:10:02+00:00
State: open

I noticed that in various places the storage types in SciD (e.g. PackedStorage) have the following postblit:

this( this ) {
containerRef_ = ContainerRef( containerRef_.ptr );
}

When ContainerRef is a RefCounted!(SomeType), you effectively set the ref count of the copy to 1. There are two issues here:

1. I can't for the life of me wrap my head around why this is done. Is this a holdover from an older design that you forgot to remove?

2. It breaks when returning a storage object from a function where NRVO isn't used. This happens in GDC due to a bug, and in DMD when the return is based on a conditional. (I'm not sure whether this is a a bug also, because the spec isn't clear enough.)

Test case:

// test.d
import scid.matrix;

Matrix!double getMat(int i) {
auto a = Matrix!double([[1.0, 2, 3], [4.0, 5, 6]]);
auto b = Matrix!double([[7.0, 8, 9], [3.0, 2, 1]]);

return (i == 42) ? a : b;
}

void main() {
auto a = getMat(0);
}

Result:

An assertion failure in the d'tor of RefCounted on exiting main() because we're trying to decrement a ref count that's already zero.

dsimcha@debian:~$ ./test
core.exception.AssertError@std.typecons(2496): Assertion failure
----------------
./test(_d_assertm+0x2a) [0x61e8a2]
./test() [0x622b52]
./test(void std.typecons.__T10RefCountedTS4scid7storage9cowmatrix45__T9CowMatrixTdVE4scid6matrix12StorageOrder1Z9CowMatrixVE3std8typecons24RefCountedAutoInitialize1Z.RefCounted.__dtor()+0x32) [0x5ce92e]
./test(void scid.storage.generalmat.BasicGeneralMatrixStorage!(std.typecons.__T10RefCountedTS4scid7storage9cowmatrix45__T9CowMatrixTdVE4scid6matrix12StorageOrder1Z9CowMatrixVE3std8typecons24RefCountedAutoInitialize1Z.RefCounted).BasicGeneralMatrixStorage.__fieldDtor()+0x15) [0x5f4ab5]
./test(void scid.matrix.BasicMatrix!(scid.storage.generalmat.BasicGeneralMatrixStorage!(std.typecons.__T10RefCountedTS4scid7storage9cowmatrix45__T9CowMatrixTdVE4scid6matrix12StorageOrder1Z9CowMatrixVE3std8typecons24RefCountedAutoInitialize1Z.RefCounted).BasicGeneralMatrixStorage).BasicMatrix.__fieldDtor()+0x15) [0x5fc199]
./test(_Dmain+0x1c) [0x5cb44c]
./test(extern (C) int rt.dmain2.main(int, char**).void runMain()+0x17) [0x61eed7]
./test(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x61ea7e]
./test(extern (C) int rt.dmain2.main(int, char**).void runAll()+0x42) [0x61ef2a]
./test(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x61ea7e]
./test(main+0xd3) [0x61ea0f]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd) [0x7f01cdaa9ead]