digitalmars.D.learn - Unexpected memory reuse
- Anonymous (39/39) Jul 31 2014 module test;
- Anonymous (1/1) Jul 31 2014 Whoops, that is writeln("a ",a.arr); and so on.
- Sean Kelly (2/2) Jul 31 2014 This looks like an optimizer bug. Do you see the same result
- Anonymous (3/5) Jul 31 2014 I get it regardless of -release or -O.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (21/25) Jul 31 2014 This allocates an array with `sz` elements once _at compile
- bearophile (4/9) Jul 31 2014 Right. It's not a compiler bug. Dmd/ldc are working correctly.
- Sean Kelly (5/17) Jul 31 2014 Huh. For some reason I thought in-class initializations like
module test; import std.stdio; class buffer(T, size_t sz) { auto arr = new T[sz]; enum end = sz-1; } void foo(T, size_t sz)() { auto buf = new buffer!(T,sz); writeln("before ", buf.arr); foreach(ref ele; buf.arr) ++ele; writeln("after ", buf.arr); } unittest { foo!(uint,4); foo!(uint,4); auto a = new buffer!(uint,4); writeln(a.arr); auto b = new buffer!(uint,4); writeln(b.arr); } void main() { auto c = new buffer!(uint,4); writeln(c.arr); } rdmd -unittest test.d before [0, 0, 0, 0] after [1, 1, 1, 1] before [1, 1, 1, 1] after [2, 2, 2, 2] a [2, 2, 2, 2] b [2, 2, 2, 2] c [2, 2, 2, 2] [Finished in 1.3s] I narrowed this down after much frustration. I'm using some fixed size buffers and thought it useful to define the size as part of the type, from which other aspects could be statically derived. Apparently it's not so useful. So I guess I can refactor the buffer's array length into the constructor or something, but I really didn't see this kind of memoization(?) coming.
Jul 31 2014
This looks like an optimizer bug. Do you see the same result with -release set vs. not, etc?
Jul 31 2014
On Thursday, 31 July 2014 at 18:51:09 UTC, Sean Kelly wrote:This looks like an optimizer bug. Do you see the same result with -release set vs. not, etc?I get it regardless of -release or -O. Replacing the arr declaration with T[sz] arr; fixes the problem.
Jul 31 2014
On Thursday, 31 July 2014 at 18:30:41 UTC, Anonymous wrote:module test; import std.stdio; class buffer(T, size_t sz) { auto arr = new T[sz];This allocates an array with `sz` elements once _at compile time_, places it somewhere into the executable, and uses its address as the default initializer for the member `arr`. All instances of `buffer` (with the same template parameters) that you create and don't change `arr` have it point to the same memory. Use this instead: class buffer(T, size_t sz) { T[sz] arr; enum end = sz-1; } This embeds `arr` into the class, instead of making it a reference to a dynamic array. If you want the latter, use this: class buffer(T, size_t sz) { T[] arr; enum end = sz-1; this() { arr = new T[sz]; } }
Jul 31 2014
Marc Schütz:Right. It's not a compiler bug. Dmd/ldc are working correctly. Bye, bearophileclass buffer(T, size_t sz) { auto arr = new T[sz];This allocates an array with `sz` elements once _at compile time_, places it somewhere into the executable, and uses its address as the default initializer for the member `arr`.
Jul 31 2014
On Thursday, 31 July 2014 at 19:28:24 UTC, Marc Schütz wrote:On Thursday, 31 July 2014 at 18:30:41 UTC, Anonymous wrote:Huh. For some reason I thought in-class initializations like this were effectively rewritten to occur as a part of the class ctor. But looking at the docs I guess this actually affects the format of the static initializer.module test; import std.stdio; class buffer(T, size_t sz) { auto arr = new T[sz];This allocates an array with `sz` elements once _at compile time_, places it somewhere into the executable, and uses its address as the default initializer for the member `arr`. All instances of `buffer` (with the same template parameters) that you create and don't change `arr` have it point to the same memory.
Jul 31 2014