digitalmars.D.learn - Returning dynamic array from the function
- m0rph (20/20) Oct 17 2012 I tryed to learn how arrays works and found another strange thing:
- Simen Kjaeraas (5/24) Oct 17 2012 b1 points to the exact same data as does a1. This data is stack-
- sclytrack (7/36) Oct 17 2012 It doesn't give an error when marking the function with safe.
- bearophile (6/11) Oct 17 2012 I think marking it @safe is not relevant. In theory a good type
- Jonathan M Davis (13/24) Oct 17 2012 @safe is irrelevant, because the code is just plain broken in the first ...
- Era Scarecrow (4/9) Oct 17 2012 Hmmm, you could have the compiler add a runtime check and see if
- bearophile (7/8) Oct 17 2012 I think there are type systems able to always catch this kind of
- timewulf (19/27) Jan 29 2013 Hi, sorry, I didn't see this thread earlier.
- Marco Cosentino (8/8) Jun 14 2014 Hi,
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (9/16) Jun 14 2014 int[] foo() {
- Marco Cosentino (6/8) Jun 14 2014 Thanks for the answer.
- monarch_dodra (5/13) Jun 14 2014 Simply "int[] = [4,2,3,1];" will do. Arrays are always created on
- sclytrack (3/15) Oct 17 2012 If that's the case then they should call it safeR D instead of
- Timon Gehr (3/20) Oct 17 2012 I think what he meant to say was that it should be illegal to do this
- Jonathan M Davis (5/9) Oct 17 2012 It looks like taking the address of a local variable already is @system,...
- m0rph (2/4) Oct 17 2012 Thanks for explanation, I thought contetns of a1 are copied to
I tryed to learn how arrays works and found another strange thing: import std.stdio; int[] create() { int[5] a1 = [ 10, 20, 30, 40, 50 ]; int[] b1 = a1; writeln("b1: ", b1); return b1; } void main() { int[] a2 = create(); writeln("a2: ", a2); } Result of execution: b1: [10, 20, 30, 40, 50] a2: [-142625792, 32767, 4358059, 0, 5] Please explain what's wrong with this code? Why variable a2 contains crap? Is this another dmd/druntime bug or I missed something?
Oct 17 2012
On 2012-10-17, 21:17, m0rph wrote:I tryed to learn how arrays works and found another strange thing: import std.stdio; int[] create() { int[5] a1 = [ 10, 20, 30, 40, 50 ]; int[] b1 = a1; writeln("b1: ", b1); return b1; } void main() { int[] a2 = create(); writeln("a2: ", a2); } Result of execution: b1: [10, 20, 30, 40, 50] a2: [-142625792, 32767, 4358059, 0, 5] Please explain what's wrong with this code? Why variable a2 contains crap? Is this another dmd/druntime bug or I missed something?b1 points to the exact same data as does a1. This data is stack- allocated, and thus a2 points to an overwritten stack frame. -- Simen
Oct 17 2012
On Wednesday, 17 October 2012 at 19:22:05 UTC, Simen Kjaeraas wrote:On 2012-10-17, 21:17, m0rph wrote:It doesn't give an error when marking the function with safe. safe int[] create() { }I tryed to learn how arrays works and found another strange thing: import std.stdio; int[] create() { int[5] a1 = [ 10, 20, 30, 40, 50 ]; int[] b1 = a1; writeln("b1: ", b1); return b1; } void main() { int[] a2 = create(); writeln("a2: ", a2); } Result of execution: b1: [10, 20, 30, 40, 50] a2: [-142625792, 32767, 4358059, 0, 5] Please explain what's wrong with this code? Why variable a2 contains crap? Is this another dmd/druntime bug or I missed something?b1 points to the exact same data as does a1. This data is stack- allocated, and thus a2 points to an overwritten stack frame.
Oct 17 2012
sclytrack:It doesn't give an error when marking the function with safe. safe int[] create() { }I think marking it safe is not relevant. In theory a good type system should give an error message on similar code. I don't know if D is supposed to spot similar error situations. Bye, bearophile
Oct 17 2012
On Wednesday, October 17, 2012 21:46:50 bearophile wrote:sclytrack:safe is irrelevant, because the code is just plain broken in the first place. It really should be an error ( http://d.puremagic.com/issues/show_bug.cgi?id=7087 ), just like it's an error to return a pointer to a local variable. But unfortunately, since all it takes to trick the compiler is passing the slice (or pointer in the case of the pointer to a local variable) to a function which then returns that slice/pointer, there's no way for the compiler to always catch it for you. The only way that safe could really be applicable would be if it became system to take the address of a local variable or to slice a static array. And perhaps it should be, but that and catching the most obvious cases are all that the compiler could do to catch this for you. - Jonathan M DavisIt doesn't give an error when marking the function with safe. safe int[] create() { }I think marking it safe is not relevant. In theory a good type system should give an error message on similar code. I don't know if D is supposed to spot similar error situations.
Oct 17 2012
The only way that safe could really be applicable would be if it became system to take the address of a local variable or to slice a static array. And perhaps it should be, but that and catching the most obvious cases are all that the compiler could do to catch this for you.Hmmm, you could have the compiler add a runtime check and see if slices are stack allocated (EAX >= ESP I think), then quit with an error, or alternatively it would make a copy afterwards, or at least a warning.
Oct 17 2012
Jonathan M Davis:there's no way for the compiler to always catch it for you.<I think there are type systems able to always catch this kind of bug (conservative region analysis, it means that if it can't demonstrate the memory doesn't escape, it prudently refuses the code). D doesn't have such kind of type system. Bye, bearophile
Oct 17 2012
On Wednesday, 17 October 2012 at 20:38:03 UTC, bearophile wrote:Jonathan M Davis:Hi, sorry, I didn't see this thread earlier. I'm new with the D-Language, but very interested. My opinion is, that this behaviour mustn't be allowed with any modern compiler. The solution isn't as complicated as it looks on first hand: The compiler will just have to test, if a return-value has got an address on the stack of the function, what shall just even be closed. The actual code doesn't calculate any pointer addresses by hand. The address is on the stack, because of the declaration of a1. b1 takes over this address and therefor there must be a flag in the symboltable, indicating it mustn't be used for return-value. This doesn't have to do anything with safe or pure. It's an error in any code. Think of the following: What will happen with a2, when for example a2 will be given a new value? It's actual address points on a deprecated address on stack. The resulting runtime errors one can just imagine.there's no way for the compiler to always catch it for you.<I think there are type systems able to always catch this kind of bug (conservative region analysis, it means that if it can't demonstrate the memory doesn't escape, it prudently refuses the code). D doesn't have such kind of type system. Bye, bearophile
Jan 29 2013
Hi, I'm new to D and stumbled upon this very interesting discussion. My question now is: can you provide an example of how to return a collection of homogeneous elements whose size is not known at compile time (for wich you would normally use a dynamic array) from a function? Thanks, Marco
Jun 14 2014
On Saturday, 14 June 2014 at 14:02:52 UTC, Marco Cosentino wrote:Hi, I'm new to D and stumbled upon this very interesting discussion. My question now is: can you provide an example of how to return a collection of homogeneous elements whose size is not known at compile time (for wich you would normally use a dynamic array) from a function?int[] foo() { int[] data = [1,2,3,4]; // create new array on the heap data ~= [5,6,7,8]; // append some data return data; } The problem with the OP's code was not per se that he returned a slice, but that he took this slice from a fixed-length local array. The example above doesn't do that, and is therefore safe.
Jun 14 2014
int[] data = [1,2,3,4]; // create new array on the heapThanks for the answer. This is the bit of information I was missing: how to create an array in the heap. Is also this a valid way to do so? int[] data = new int[0]; data ~= [4,2,3,1];
Jun 14 2014
On Saturday, 14 June 2014 at 21:37:51 UTC, Marco Cosentino wrote:Simply "int[] = [4,2,3,1];" will do. Arrays are always created on the heap by default. To override that, you can assign to a static array, which resides on the the stack. Then you slice your static array.int[] data = [1,2,3,4]; // create new array on the heapThanks for the answer. This is the bit of information I was missing: how to create an array in the heap. Is also this a valid way to do so? int[] data = new int[0]; data ~= [4,2,3,1];
Jun 14 2014
On Wednesday, 17 October 2012 at 19:46:51 UTC, bearophile wrote:sclytrack:If that's the case then they should call it safeR D instead of safe D.It doesn't give an error when marking the function with safe. safe int[] create() { }I think marking it safe is not relevant. In theory a good type system should give an error message on similar code. I don't know if D is supposed to spot similar error situations. Bye, bearophile
Oct 17 2012
On 10/17/2012 10:15 PM, sclytrack wrote:On Wednesday, 17 October 2012 at 19:46:51 UTC, bearophile wrote:I think what he meant to say was that it should be illegal to do this even in system code, not that it is OK that it passes with safe.sclytrack:If that's the case then they should call it safeR D instead of safe D.It doesn't give an error when marking the function with safe. safe int[] create() { }I think marking it safe is not relevant. In theory a good type system should give an error message on similar code. I don't know if D is supposed to spot similar error situations. Bye, bearophile
Oct 17 2012
On Wednesday, October 17, 2012 13:07:13 Jonathan M Davis wrote:The only way that safe could really be applicable would be if it became system to take the address of a local variable or to slice a static array. And perhaps it should be, but that and catching the most obvious cases are all that the compiler could do to catch this for you.It looks like taking the address of a local variable already is system, but taking a slice of a static array is not. That really should change: http://d.puremagic.com/issues/show_bug.cgi?id=8838 - Jonathan M Davis
Oct 17 2012
b1 points to the exact same data as does a1. This data is stack- allocated, and thus a2 points to an overwritten stack frame.Thanks for explanation, I thought contetns of a1 are copied to the heap when assignment operator executed.
Oct 17 2012