www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Stack or heap? What's that?

reply orgoton <orgoton mindless.com> writes:
One difference between C and D is that data is allocated on the heap instead
of the stack or something like that. What does that mean?

Also, I have a problem in a program of mine. It's something like

Open up a file using C functions FILE * file=fopen(filename, 'r');
I read in two numbers which represent the size of my table. On the private
part of the class I have int table[][];
Not i put table.length=size1; Next foreach (int[] segment; table[])
segment.length=size2;

Next I want to read the data from the file and voilá! Function fread fails! (0
bytes read).

I rewrote it:
table.length=size1;
for auto i=0; i<size1; i++)
for (auto j=0; j<size2; j++)
{
int number;
fread(file, &number);
table[i]~=number;
}

This works as expected. This is slower of course, because at each iteration it
has to reserve more memory. The algorith is basically the same. Initially I
blammed the GC but when I disable() it or even addRoot(file) it still doesn't
work, so I settled for the second way.
Jan 12 2007
next sibling parent Carlos Santander <csantander619 gmail.com> writes:
orgoton escribió:
 One difference between C and D is that data is allocated on the heap instead
 of the stack or something like that. What does that mean?
 
 Also, I have a problem in a program of mine. It's something like
 
 Open up a file using C functions FILE * file=fopen(filename, 'r');
 I read in two numbers which represent the size of my table. On the private
 part of the class I have int table[][];
 Not i put table.length=size1; Next foreach (int[] segment; table[])
 segment.length=size2;
 
 Next I want to read the data from the file and voil�! Function fread fails!
(0
 bytes read).
 

Use foreach (inout int[] segment; table[])
 I rewrote it:
 table.length=size1;
 for auto i=0; i<size1; i++)
 for (auto j=0; j<size2; j++)
 {
 int number;
 fread(file, &number);
 table[i]~=number;
 }
 

You could also set the length before the second for.
 This works as expected. This is slower of course, because at each iteration it
 has to reserve more memory. The algorith is basically the same. Initially I
 blammed the GC but when I disable() it or even addRoot(file) it still doesn't
 work, so I settled for the second way.

-- Carlos Santander Bernal
Jan 12 2007
prev sibling next sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
orgoton wrote:
 One difference between C and D is that data is allocated on the heap instead
 of the stack or something like that.

Not much like that, actually. Variables of primitive, struct, union and static array types are allocated on the stack. Dynamic arrays and class objects are allocated on the heap. Of course, if such types are declared as local variables, then references to this data on the heap will be allocated on the stack.
 What does that mean?

A stack is a last in first out (LIFO) buffer. _The_ stack is the LIFO buffer that keeps track of the current nesting of function calls and the values of local variables. The heap is an area of memory set aside for dynamic allocation. In C++, the new and delete keywords are used to allocate and deallocate memory on the heap. In D, the following actions allocate memory on the heap: - creating a new object or array using new - setting the .length of a dynamic array, if it hasn't already been allocated or needs to grow and there isn't room for it to grow in place - concatenating arrays using ~= under the same conditions - concatenating arrays using ~ - calling .dup on an array and the garbage collector deallocates memory, so normally you don't need to worry about memory management. Usually, the only time you need to worry about whether something's on the heap or the stack is when returning from a function. A common newbie error seems to be to do something like int[] returnAnArray() { int[10] result; result[] = 42; return result; } which won't work because you're returning a reference to data held on the stack, and this reference will be invalid once the function has returned. For it to work, you'd have to cause the array to be on the heap by doing either int[] result = new int[10]; or int[] result; result.length = 10; or return a copy of the array instead: return result.dup; Of course, it's OK to do something like int returnAnInt() { int result = 69; return result; } since an int is returned by value - but usually you wouldn't declare a result variable like this unless you were doing something more involved. HTH Stewart.
Jan 13 2007
prev sibling next sibling parent Steve Horne <stephenwantshornenospam100 aol.com> writes:
On Fri, 12 Jan 2007 18:34:41 +0000 (UTC), orgoton
<orgoton mindless.com> wrote:

One difference between C and D is that data is allocated on the heap instead
of the stack or something like that. What does that mean?

The word 'stack' can refer to any data structure that works in a last-in-first-out fashion. 'The stack' normally refers to a special stack used by the processor. When you call a procedure or a function, the stack is used to remember where to return to when that procedure or function is finished. It is also commonly used to store the local variables for each procedure or function that is currently executing. Memory that is requested when needed and freed when not needed (generally independently of procedure calls and returns) comes from the heap, which is a data structure designed to handle random-order allocation and freeing of chunks of memory. This is not the only meaning of the word 'heap' - the word also refers to a data structure used to efficiently handle priority queues. In C, memory is allocated on the heap using malloc and free. In C++ it is allocated on the heap using new and delete. The stack is very convenient and efficient. For example, it is easy for the processor to find particular variables on the stack - they are always at a fixed position (determined by the compiler) relative to the stack pointer. Only global variables are more convenient and efficient (since they are always at exactly the same location). The heap is more problematic since effort is need to keep track of where in memory each heap-allocated object is stored. Heap allocated objects can only be accessed via pointers/references (which may be stored on the stack or in a global variable, or in another heap-allocated objects). However, heap allocated memory is much more flexible. In D (and Java, C# etc), things are slightly complicated by the garbage collection and the use of reference semantics. The basic result is that a local variable that is a class instance will be allocated on the heap, unlike in C++ where it would be allocated on the stack. D does, however, hold a reference to the object on the stack. This means that when the function exits, only the reference is automatically destroyed. The object itself may still exist for some time, and will not be destroyed at all if some other reference to it exists. When the garbage collector determines that no further references to it exist, it will be cleaned up and the memory for the object will be returned to the heap. Some of the above statements are actually technically inaccurate in modern PCs, because of the way modern computers manage memory, but they do represent the applications view of memory quite accurately. Stewart Gordon has already listed the different types that are allocated from the heap even when used as local variables (since they are reference types) - I just thought I'd add some more explanation. -- Remove 'wants' and 'nospam' from e-mail.
Jan 14 2007
prev sibling parent reply Manfred Hansen <m.hansen kielnet.net> writes:
orgoton wrote:

 One difference between C and D is that data is allocated on the heap
 instead of the stack or something like that. What does that mean?
 
 Also, I have a problem in a program of mine. It's something like
 
 Open up a file using C functions FILE * file=fopen(filename, 'r');
 I read in two numbers which represent the size of my table. On the private
 part of the class I have int table[][];
 Not i put table.length=size1; Next foreach (int[] segment; table[])
 segment.length=size2;
 
 Next I want to read the data from the file and voil??! Function fread
 fails! (0 bytes read).
 
 I rewrote it:
 table.length=size1;
 for auto i=0; i<size1; i++)
 for (auto j=0; j<size2; j++)
 {
 int number;
 fread(file, &number);
 table[i]~=number;
 }
 
 This works as expected. This is slower of course, because at each
 iteration it has to reserve more memory. The algorith is basically the
 same. Initially I blammed the GC but when I disable() it or even
 addRoot(file) it still doesn't work, so I settled for the second way.

One question. What do the destructor ~this ? Delete he also the reference on the stack to the object in the heap ? Manfred
Jan 15 2007
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Manfred Hansen wrote:
<snip>
 One question. What do the destructor ~this ?
 Delete he also the reference on the stack to the object
 in the heap ? 

No. The destructor is automatically called when the GC detects that the object is no longer reachable, just before it releases the memory held by it. If you trigger the destructor to run by a DeleteExpression, then file:///e:/dmd/html/d/expression.html#DeleteExpression "The pointer, dynamic array, or reference is set to null after the delete is performed." For example: class Qwert {} void main() { Qwert yuiop = new Qwert; delete yuiop; assert (yuiop is null); } but this behaviour is part of DeleteExpression, not of the destructor. Stewart.
Jan 16 2007