www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Segfault with std.container.Array but not regular dynamic array

Hello all,

I'm writing some code which is meant to represent a network of linked nodes.

Each node is represented by a struct that contains the node's ID and an array
of 
links to other nodes.  Just as an experiment, I've tried out two different ways 
of doing this:

////////////////////////////////////////////////////////////////
struct Node1
{
	uint id;
	Link[] links;

	this(uint id)
	{
		this.id = id;
	}

	void addLink(uint l)
	{
		links ~= Link(l);
	}
}

struct Node2
{
	uint id;
	Array!(Link) links;

	this(uint id)
	{
		this.id = id;
	}

	void addLink(uint l)
	{
		links.insert(Link(l));
	}
}
////////////////////////////////////////////////////////////////

Now, either of these seem to work fine per se.  Just as a simple test, you can 
do something like,

	auto n1 = Node1(1);
	auto n2 = Node2(2);

	n1.addLink(5);
	n1.addLink(6);
	writeln(n1.links[0].id, "\t", n1.links[1].id);

	n2.addLink(7);
	n2.addLink(8);
	writeln(n2.links[0].id, "\t", n2.links[1].id);

... and all the correct results come out as you'd expect.

Now, suppose I want to implement a struct that groups together these nodes. 
Here's a go:

////////////////////////////////////////////////////////////////
struct Network(Node)
{
	Node[uint] nodes;

	void add(uint i, uint j)
	{
		if((i in nodes) is null)
			nodes[i] = Node(i);
		if((j in nodes) is null)
			nodes[j] = Node(j);

		nodes[i].addLink(j);
		nodes[j].addLink(i);
	}

	void print()
	{
		foreach(k; nodes.keys)
		{
			write("[", k, "]");
			foreach(l; nodes[k].links)
				write(" ", l.id);
			writeln();
		}
		writeln();
	}
}
////////////////////////////////////////////////////////////////

However, while this structure (which is essentially a wrapper around an 
associative array between node IDs and actual nodes) works fine with Node1, the 
dynamic array-based node structure, it fails with Node2, which is based on 
std.container.Array.

e.g. this works:

	Network!Node1 net1;
	net1.add(1, 5);
	net1.print();
	net1.add(1, 6);
	net1.print();

... but this segfaults:

	Network!Node2 net2;
	net2.add(1, 7);

I'm a bit confused as to why.  By the look of things it's actually the creation 
of new entries in the Node[uint] associative array, rather than appending links 
to the individual nodes.  Can anyone advise?

Full working (or rather, failing:-) code attached for reference.

On a slightly different note, where std.container.Array is concerned: how come
I 
can't use a foreach(i, x; myArray) formulation?  I.e. one where the foreach can 
infer the index value as well as the contained value ...
Nov 26 2012