www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Using emplace leading to memory corruption

reply d coder <dlang.coder gmail.com> writes:
Greetings

I am trying to use emplace and it is seemingly leading to memory
corruption. Before I file a bug on DMD Buzilla, I want to find out if I am
doing something wrong or if it is a known issue. I am using a linux box and
this testcase is freaky -- if I comment out either line 20 or line 24, the
segfault vanishes.

Thanks
- Puneet

$ rdmd --force -version=EMPLACE -Isrc -J.. test.d
4000
Segmentation fault (core dumped)
$ rdmd --force -Isrc -J.. test.d
4000

struct bdd {}                                              // 01
class Frop {                                               // 02
  int[] _var;                                              // 03
  int[] var() {                                            // 04
    return _var;                                           // 05
  }                                                        // 06
  this() {                                                 // 07
    this._var.length = 1;                                  // 08
  }                                                        // 09
}                                                          // 10
class Foo {                                                // 11
  long[] nodes;                                            // 12
  Frop[] frops;                                            // 13
  long[] table;                                            // 14
  this() {                                                 // 15
    nodes.length = 120000;                                 // 16
    frops.length = 1;                                      // 17
    frops[0] = new Frop();                                 // 18
    initTable();                                           // 19
    zoo(frops[0].var);                                     // 20
  }                                                        // 21
  void initTable() {                                       // 22
    import std.stdio;                                      // 23
    writeln(4000);                                         // 24
    table.length = 40000;                                  // 25
  }                                                        // 26
  void zoo(int[] varset) {}                                // 27
}                                                          // 28
class Bar {                                                // 29
  Foo _foo;                                                // 30
  this() {                                                 // 31
    version(EMPLACE) {                                     // 32
      import std.conv, core.stdc.stdlib;                   // 33
      enum size_t size = __traits(classInstanceSize, Foo); // 34
      assert(size is 32);                                  // 35
      void* tmp = core.stdc.stdlib.malloc(size);           // 36
      if (!tmp)                                            // 37
        throw new Exception("Memory allocation failed");   // 38
      void[] mem = tmp[0..size];                           // 39
      _foo = emplace!(Foo)(mem);                           // 40
    }                                                      // 41
    else {                                                 // 42
      _foo = new Foo();                                    // 43
    }                                                      // 44
  }                                                        // 45
}                                                          // 46
void main() {                                              // 47
  auto bar = new Bar;                                      // 48
}                                                          // 49
Sep 28 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 29 September 2013 at 07:03:30 UTC, d coder wrote:
 Greetings

 I am trying to use emplace and it is seemingly leading to memory
 corruption. Before I file a bug on DMD Buzilla, I want to find 
 out if I am
 doing something wrong or if it is a known issue. I am using a 
 linux box and
 this testcase is freaky -- if I comment out either line 20 or 
 line 24, the
 segfault vanishes.

 Thanks
 - Puneet
I didn't see anything obviously wrong with your code. Remember though that when emplacing a class over some memory, you must account for any extra alignment (though that doesn't seem to be a problem here). Any chance you could simplify this and file it?
Sep 29 2013
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/29/13, monarch_dodra <monarchdodra gmail.com> wrote:
 Remember though that when emplacing a class over some memory, you
 must account for any extra alignment (though that doesn't seem to
 be a problem here).
emplace does do a check for misalignment this internally with the testEmplaceChunk helper function. It would throw otherwise.
Sep 29 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 29 September 2013 at 09:46:04 UTC, Andrej Mitrovic 
wrote:
 On 9/29/13, monarch_dodra <monarchdodra gmail.com> wrote:
 Remember though that when emplacing a class over some memory, 
 you
 must account for any extra alignment (though that doesn't seem 
 to
 be a problem here).
emplace does do a check for misalignment this internally with the testEmplaceChunk helper function. It would throw otherwise.
Right, emplace *checks*, which means caller must take it into account. This doesn't explain the issue, but it should be kept in mind when making the allocation, and building the slice. OP clearly just assumed his slice would be aligned.
Sep 29 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 29 September 2013 at 08:21:34 UTC, monarch_dodra wrote:
 I didn't see anything obviously wrong with your code.
Did some more toying around. I did notice an issue in emplace, but nothing that would explain what you are observing. By replacing your block with: //---- version(EMPLACE) { //Allocation import core.stdc.stdlib; enum size_t size = __traits(classInstanceSize, Foo); auto tmp = cast(byte*)core.stdc.stdlib.malloc(size); if (!tmp) throw new Exception("Memory allocation failed"); assert (cast(size_t)tmp % 16 == 0); //Result auto result = cast(Foo)tmp; //Construction auto mem = tmp[0..size]; auto init = typeid(Foo).init; assert(init.ptr); mem[] = init[]; result.__ctor(); //Finished building, assign _foo = result; } //---- I'm observing the same behavior (Killed by signal 11). I *think* the code is bug free, so I'm leaning towards a code gen bug. Another thing I noticed is that if I call a class function on a null instance, I'm not getting a NullObjectError. I thought I was supposed to...?
Sep 29 2013
prev sibling parent reply "lomereiter" <lomereiter gmail.com> writes:
You didn't tell GC that the allocated memory contains pointers to 
GC'd data.
Therefore, it thinks that the class members can be freed, which 
is not the case.

Adding lines
 import core.memory; GC.addRange(tmp, size);
resolves the problem. You must also call GC.removeRange(tmp) when you will free the allocated memory.
       void[] mem = tmp[0..size];                           // 39
       _foo = emplace!(Foo)(mem);                           // 40
Sep 29 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/29/13 5:29 AM, lomereiter wrote:
 You didn't tell GC that the allocated memory contains pointers to GC'd
 data.
 Therefore, it thinks that the class members can be freed, which is not
 the case.

 Adding lines
 import core.memory; GC.addRange(tmp, size);
resolves the problem. You must also call GC.removeRange(tmp) when you will free the allocated memory.
       void[] mem = tmp[0..size];                           // 39
       _foo = emplace!(Foo)(mem);                           // 40
I tried that and it still crashes. I don't think that's the problem. Puneet, the code looks legit, please file a bug report. Andrei
Sep 29 2013
parent d coder <dlang.coder gmail.com> writes:
 I tried that and it still crashes. I don't think that's the problem.
 Puneet, the code looks legit, please file a bug report.
Thanks for confirming. http://d.puremagic.com/issues/show_bug.cgi?id=11139 Regards - Puneet
Sep 29 2013