Thread overview
Strange seg fault
Jun 12, 2013
gedaiu
Jun 12, 2013
Adam D. Ruppe
Jun 12, 2013
Ali Çehreli
Jun 13, 2013
gedaiu
Jun 13, 2013
Ali Çehreli
Jun 14, 2013
Ali Çehreli
June 12, 2013
Hi,

Can anyone help me why this code goes wrong? I get exit code 139 with DMD 2.063


import std.stdio;



struct Test {
	string val = "";
	string[] key;
	
	/**
	 * operator "=" overload
	 */
	Test opAssign(string val){
		this.val = val;
		
		string[1] t;
		t = val;
		
		key ~= t;
		
		return this;
	}
	
	Test opAssign(Test val){
		this.val = val.val;
		
		key ~= val.key;
		
		return this;
	}
	
	void append(Test t) {
		val ~= t.val;
		key ~= t.key;
	};
}

void main() {
	
	Test val;
	val = "test";
	
	Test[string] data;
	Test v;
	v = "asd";
	data["test"] = v;
	
	writeln(v);
	writeln(data["test"]);
	
	data["test"].append(val);
	
	
	writeln(data["test"].key);
	writeln("done");
}

Thanks,
Bogdan
June 12, 2013
I think you've hit bug city in the associative array implementation. The "this" in there doesn't seem to point at anything meaningful. This is probably worthy of a bug report.

A potential workaround is to store pointers to your structs in the associative array, that way you can set them up ahead of time, then just do data["test"] = ptr; instead.
June 12, 2013
On 06/12/2013 01:12 PM, gedaiu wrote:

> Hi,
>
> Can anyone help me why this code goes wrong? I get exit code 139 with
> DMD 2.063
>
>
> import std.stdio;
>
>
>
> struct Test {
>      string val = "";
>      string[] key;
>
>      /**
>       * operator "=" overload
>       */
>      Test opAssign(string val){
>          this.val = val;
>
>          string[1] t;
>          t = val;
>
>          key ~= t;

Instead of the last three lines:

    key ~= val;

However, if you really wanted a 1-element fixed-length array then:

    string[1] t = [ val ];

>          return this;
>      }
>

Remove the following opAssign altogether:

>      Test opAssign(Test val){
>          this.val = val.val;
>
>          key ~= val.key;
>
>          return this;
>      }

As general rules:

* Define a post-blit only if the code would be incorrect if you don't do that. (For example, it may be incorrect that two objects share the same array.)

* Define an opAssign from the same type only if your implementation will be more efficient than the compiler's safe alternative, which happens to be "first copy, then swap." For example, instead of copying a member array, you may decide to reuse it.

>      void append(Test t) {
>          val ~= t.val;
>          key ~= t.key;
>      };
> }
>
> void main() {
>
>      Test val;
>      val = "test";
>
>      Test[string] data;
>      Test v;
>      v = "asd";
>      data["test"] = v;
>
>      writeln(v);
>      writeln(data["test"]);
>
>      data["test"].append(val);
>
>
>      writeln(data["test"].key);
>      writeln("done");
> }
>
> Thanks,
> Bogdan

Ali

June 13, 2013
Hi,

How should i submit this bug?

Thanks,
Bogdan

On Wednesday, 12 June 2013 at 20:49:54 UTC, Ali Çehreli wrote:
> On 06/12/2013 01:12 PM, gedaiu wrote:
>
> > Hi,
> >
> > Can anyone help me why this code goes wrong? I get exit code
> 139 with
> > DMD 2.063
> >
> >
> > import std.stdio;
> >
> >
> >
> > struct Test {
> >      string val = "";
> >      string[] key;
> >
> >      /**
> >       * operator "=" overload
> >       */
> >      Test opAssign(string val){
> >          this.val = val;
> >
> >          string[1] t;
> >          t = val;
> >
> >          key ~= t;
>
> Instead of the last three lines:
>
>     key ~= val;
>
> However, if you really wanted a 1-element fixed-length array then:
>
>     string[1] t = [ val ];
>
> >          return this;
> >      }
> >
>
> Remove the following opAssign altogether:
>
> >      Test opAssign(Test val){
> >          this.val = val.val;
> >
> >          key ~= val.key;
> >
> >          return this;
> >      }
>
> As general rules:
>
> * Define a post-blit only if the code would be incorrect if you don't do that. (For example, it may be incorrect that two objects share the same array.)
>
> * Define an opAssign from the same type only if your implementation will be more efficient than the compiler's safe alternative, which happens to be "first copy, then swap." For example, instead of copying a member array, you may decide to reuse it.
>
> >      void append(Test t) {
> >          val ~= t.val;
> >          key ~= t.key;
> >      };
> > }
> >
> > void main() {
> >
> >      Test val;
> >      val = "test";
> >
> >      Test[string] data;
> >      Test v;
> >      v = "asd";
> >      data["test"] = v;
> >
> >      writeln(v);
> >      writeln(data["test"]);
> >
> >      data["test"].append(val);
> >
> >
> >      writeln(data["test"].key);
> >      writeln("done");
> > }
> >
> > Thanks,
> > Bogdan
>
> Ali

June 13, 2013
On 06/12/2013 11:56 PM, gedaiu wrote:

> How should i submit this bug?

You can reduce it to a minimal program first and then submit at

  http://d.puremagic.com/issues/

Here is a reduced program:

struct Test {
    string[] keys;

    Test opAssign(Test rhs){
        assert(this.keys !is null);
        assert(rhs.keys is null);

        keys ~= rhs.keys;

        return this;
    }
}

void main() {
    Test[string] data;
    Test t;

    data["test"] = t;
}

The output:

  core.exception.OutOfMemoryError

The problem seems to be also related to struct initialization: As indicated by the asserts in opAssign, although main.t.keys is not null, rhs.keys is null.

Ali

June 14, 2013
On 06/13/2013 09:11 AM, Ali Çehreli wrote:
> On 06/12/2013 11:56 PM, gedaiu wrote:
>
>  > How should i submit this bug?
>
> You can reduce it to a minimal program first and then submit at
>
>    http://d.puremagic.com/issues/

Thank you for submitting it:

  http://d.puremagic.com/issues/show_bug.cgi?id=10356

Ali