Announcement

Collapse
No announcement yet.

What are Stack and Heap ?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • What are Stack and Heap ?

    Hi All

    Please pardon me as I'm only a beginner programmer, I would love to know about the usage of Stack and Heap. I found something
    in C programming http://www.programmerinterview.com/d...tack-and-heap/


    According to this article :
    How long does memory on the stack last versus memory on the heap?


    Once a function call runs to completion, any data on the stack created specifically for that function call will automatically be deleted.
    Any data on the heap will remain there until it’s manually deleted by the programmer.

  • #2
    From the standpoint of PB programming, I think that "Stack" pertains to LOCAL variables in a function or sub routines. While "Heap"
    pertains to variables that are designated as GLOBAL or STATIC , am I right here?

    Comment


    • #3
      Oversimplified, but you can think of it this way.

      The heap is the main block of memory available to the program for storing and manipulating data.
      The stack is a smaller block of memory that is used to store 32 bit values such as the pointers to memory locations in the heap where actual string data and Global/Static numeric data is stored, and also to directly store some numeric variables.

      Once a local variable goes "out of scope" i.e. the function it is declared in ends, the relevant data in the stack is destroyed and any memory it occupies in the heap becomes usable for other purposes.

      "Any data on the heap will remain there until it’s manually deleted by the programmer." Unlike C, PB does that for you automatically. (unless you use the GLOBALEM functions)
      Last edited by Stuart McLachlan; 23 Jul 2020, 06:44 PM.

      Comment


      • #4
        Tim,

        At very close range, there is no difference as memory is memory but the differences occur in where the memory is allocated and what is its intended purpose. Memory on the stack is defined in the actual executable file format and it is used for both LOCAL variables AND passing arguments from one procedure to another. In win32 it even had 2 processor registers to perform those tasks, EBP (the base pointer) and ESP (the stack pointer) and between them locals and arguments are handled in a co-operative manner.

        Dynamically allocated memory occurs in OS functions like HeapAlloc(), GlobalAlloc() and VirtualAlloc() with a few other specialised techniques as well and they are generally in the hands of the programmer to allocate, use within its bounds and release it after use. PB as a high level language gives the programmer the "basic" interface which isolates the programmer from having to deal with memory at that level but as the language is also powerful enough to handle low level functions, you can handle memory yourself once you have enough practice.
        hutch at movsd dot com
        The MASM Forum

        www.masm32.com

        Comment


        • #5
          I've always understood that heap memory allocated with STATIC, GLOBALMEM (PB) or one of the Win32API functions like HeapAlloc will NEVER move. But, LOCAL variables stored on the stack COULD move after a context switch. Is this correct? This would seem to be a possible problem. For example, a procedure (FUNCTION/SUB) could pass a pointer to a buffer (or maybe BYREF) to an external procedure for some type of modification (e.g. fill a buffer with some data). Or, maybe it's not an issue after all

          Comment


          • #6
            Originally posted by Jerry Wilson View Post
            I've always understood that heap memory allocated with STATIC, GLOBALMEM (PB) or one of the Win32API functions like HeapAlloc will NEVER move. But, LOCAL variables stored on the stack COULD move after a context switch. Is this correct? This would seem to be a possible problem. For example, a procedure (FUNCTION/SUB) could pass a pointer to a buffer (or maybe BYREF) to an external procedure for some type of modification (e.g. fill a buffer with some data). Or, maybe it's not an issue after all
            A STATIC string will change it's location if is modified with a normal PB manipulation instruction.
            So its STRPTR will change. However its VARPTR will remain the same and that is what is generally passed as a parameter

            Comment


            • #7
              Stuart is right, the processor handles task switching and your app does not have to do anything. All memory allocation API functions maintain the same address unless you modify it by making it larger. If you increase GlobalAlloc() so that the request will not fit into the same address (something else has allocated after it), GlobalReAlloc() will move the address to where it can satisfy the request. Here the pointer must be taken from the re-allocation API.
              hutch at movsd dot com
              The MASM Forum

              www.masm32.com

              Comment


              • #8
                All memory allocation API functions maintain the same address unless you modify it by making it larger .
                Just to be a little more accurate...

                "All memory [allocated by] API functions maintain the same virtual address unless you modify it by making it larger or smaller. "

                And ..

                Or, maybe it's not an issue after all
                As long as you use exclusively PB verbs, functions and statements it is not an issue. (Unless you try to get cute using pointer variables. Don't do that!). And, you can always use PBs error-trapping (ON ERROR GOTO... or even a simple test of the ERR system variable)) to test for sufficient memory availability.

                However, mixing and matching PB verbs/functions/statements with direct calls to the Windows API requires a more intimate understanding of memory management and is something I very much recommend against for relative "newbies."
                Michael Mattias
                Tal Systems Inc. (retired)
                Racine WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Hi Michael,

                  What you have said is correct for basic OLE string as it is always reallocated, for the GlobalAlloc() family of functions, this is not so. Here is the test piece.
                  Code:
                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                  
                      #include "\basic\include\win32api.inc"
                  
                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                  
                  FUNCTION PBmain as LONG
                  
                      LOCAL pMem as DWORD
                  
                      pMem = GlobalAlloc(%GMEM_FIXED,65536)               ' Alloc 64 k
                      StdOut format$(pMem)
                  
                      pMem = GlobalReAlloc(pMem,65536*2,%GMEM_MOVEABLE)   ' ReAlloc to 128 k
                      StdOut format$(pMem)
                  
                      pMem = GlobalReAlloc(pMem,65536,%GMEM_MOVEABLE)     ' ReAlloc back to 64 k again
                      StdOut format$(pMem)
                  
                      waitkey$
                  
                  End FUNCTION
                  
                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                  This is the output, you will notice that the second and third address are the same, this more efficient than relocating the entire buffer if its length is only truncated.
                  Code:
                    10352008
                    10417552
                    10417552
                  hutch at movsd dot com
                  The MASM Forum

                  www.masm32.com

                  Comment


                  • #10
                    So, this code should always be safe, yes?. A pointer to a char "buffer" (string in stack memory) is passed to a Winsock function which may take some time to complete/return. The size of the string will not change but the thread could lose context while waiting for the Winsock function to return. And please - before anyone jumps on me for wasting stack space with a large string, this is NOT part of a "real" code project. While not useful, the code will, in fact, execute correctly but will always fail with a Winsock WSANOTINITIALIZED error since Winsock is not started. I'm only concerned about the memory location of the string moving in memory (STRPTR result changes). This was the easiest example that came to mind (I never even use this Winsock function).
                    Code:
                    #COMPILE EXE
                    
                    #INCLUDE "win32api.inc"
                    
                    '-- Winsock documentation for recv() - which conflicts with PB RECV.
                    'int recv(
                    '  SOCKET s,
                    '  char   *buf,
                    '  int    len,
                    '  int    flags
                    ');
                    
                    DECLARE FUNCTION wsRecv LIB "Ws2_32.dll" ALIAS "recv" ( _
                        BYVAL hSock   AS LONG, _  ' s
                        BYVAL lpBuf   AS LONG, _  ' *buf
                        BYVAL bufSize AS LONG, _  ' len
                        BYVAL flags   AS LONG _   ' flags
                        ) AS LONG
                    
                    FUNCTION PBMAIN () AS LONG
                      LOCAL ret, hSock AS LONG
                      LOCAL sBuff AS STRING
                      sBuff = STRING$(65535, 0)
                    '... Code to start Winsock and create/open a socket goes here
                      ret = wsRecv ( _
                          hSock, _
                          STRPTR(sBuff), _  '<--- Ptr to buffer that will not change in size while
                          LEN(sBuff), _     '     waiting for wsRecv to complete
                          0 _
                          )
                      IF ret = %SOCKET_ERROR THEN
                        ret = GetLastError
                        PRINT "wsRecv failed with err =" ret
                      ELSE
                        PRINT "Number of bytes received =" ret
                      END IF
                      WAITKEY$
                    END FUNCTION

                    Comment


                    • #11
                      Hi Jerry,

                      If I understand your test piece, you create a dynamic string buffer then pass the buffer address to a Winsock function. Now as long as you don't change the string via a basic re-definition, the address will remain the same. If you are in a situation where you have to alter the buffer via basic, always grab the address immediately after you have changed the string.
                      hutch at movsd dot com
                      The MASM Forum

                      www.masm32.com

                      Comment


                      • #12
                        Originally posted by Jerry Wilson View Post
                        So, this code should always be safe, yes?. A pointer to a char "buffer" (string in stack memory) is passed to a Winsock function
                        What makes you so sure that buffer is in stack memory?

                        Is this one in stack memory?

                        '
                        Code:
                        #COMPILE EXE
                        #STACK 131072
                        
                        FUNCTION PBMAIN () AS LONG
                        LOCAL sBuff AS STRING
                        sBuff = STRING$(200000,0)
                        '...
                        END FUNCTION
                        '

                        Comment


                        • #13
                          Local v Static strings and where they are stored. This one makes if fairly clear that the actual strings are stored in the same memory area (i.e. the heap)
                          '
                          Code:
                          #COMPILE EXE
                          GLOBAL sBuff1 AS STRING
                          FUNCTION PBMAIN () AS LONG
                              STATIC sBuff2 AS STRING
                              LOCAL sBuff3 AS STRING
                              LOCAL p1,p2,p3 AS STRING PTR
                              LOCAL v1,v2,v3 AS STRING PTR
                              sBuff1 = "a"
                              sBuff2 = "b"
                              sBuff3 = "c"
                              p1 = STRPTR(SBuff1)
                              p2 = STRPTR(SBuff2)
                              p3 = STRPTR(SBuff3)
                              v1 = VARPTR(sBuff1)
                              v2 = VARPTR(sBuff2)
                              v3 = VARPTR(sBuff3)
                          
                              ? USING$("# # # # # # ", p1,p2,p3,v1,v2,v3)
                          END FUNCTION
                          '
                          In my tests, the STRPTRs are always located just 24 bytes apart.
                          It's also clear that the VARPTRs for the Global and Static are created at the same time (just 4 bytes apart) at compile time

                          Comment


                          • #14
                            STRPTR's always 24-bytes apart?
                            Code:
                            FUNCTION PBMAIN () AS LONG
                             LOCAL s1,s2 AS STRING
                             LOCAL p1,p2 AS LONG
                             s1 = "a"
                             s2 = "b"
                             p1 = STRPTR(s1)
                             p2 = STRPTR(s2)
                             ? USING$("#",p2-p1)
                            END FUNCTION
                            How long is an idea? Write it down.

                            Comment


                            • #15
                              Originally posted by Mike Doty View Post
                              STRPTR's always 24-bytes apart?
                              Code:
                              FUNCTION PBMAIN () AS LONG
                              LOCAL s1,s2 AS STRING
                              LOCAL p1,p2 AS LONG
                              s1 = "a"
                              s2 = "b"
                              p1 = STRPTR(s1)
                              p2 = STRPTR(s2)
                              ? USING$("#",p2-p1)
                              END FUNCTION
                              It is for me, I get the same every time:

                              Click image for larger version  Name:	strptr24.png Views:	0 Size:	15.2 KB ID:	797276

                              But that's not proving much since they are both Local. The key point is that whether they are Global, Static or local, the pointers are all close together in the same area of memory. (Obviously if those strings were longer, that 24 byte spacing would change and in any practical application once strings start getting creating/deleted and modified, exactly where in the heap they are stored will vary considerably).

                              People saying that Local strings are stored on the stack are thinking about C etc, not PB. PB is more like Java in the way it manages string data.

                              That's why in C you need to specifically allocate and de-allocate memory blocks for string buffers to store strings in the heap.. In PB, Bob did it all for you behind the scenes so you don't need to think about where a string is stored.

                              Comment


                              • #16
                                It is often 24, but I get all sorts of answers.
                                How long is an idea? Write it down.

                                Comment


                                • #17
                                  Originally posted by Mike Doty View Post
                                  It is often 24, but I get all sorts of answers.
                                  I've just done a Ctrl+E on your code followed by Enter to dismiss the message box about 30 times. 24 every time.

                                  Comment


                                  • #18
                                    I'm using 32-bit Windows 10 if that makes a difference.
                                    Code:
                                    FUNCTION PBMAIN () AS LONG
                                     LOCAL s1,s2 AS STRING
                                     LOCAL p1,p2 AS LONG
                                     s1 = "a"
                                     s2 = "b"
                                     s1 = STRPTR(s1)
                                     p2 = STRPTR(s2)
                                     ? USING$("#",p2-p1)
                                    END FUNCTION
                                    How long is an idea? Write it down.

                                    Comment


                                    • #19
                                      Originally posted by Mike Doty View Post
                                      I'm using 32-bit Windows 10 if that makes a difference.
                                      Code:
                                      FUNCTION PBMAIN () AS LONG
                                      LOCAL s1,s2 AS STRING
                                      LOCAL p1,p2 AS LONG
                                      s1 = "a"
                                      s2 = "b"
                                      s1 = STRPTR(s1)
                                      p2 = STRPTR(s2)
                                      ? USING$("#",p2-p1)
                                      END FUNCTION
                                      That may well make a difference, I'm using 64 bit. But as I said before, both Local so it's not proving much.

                                      Comment


                                      • #20
                                        FWIW my results for 10 runs of the code in posts 14 and 15:
                                        144, 168, 48, 24, 120, -120, 96, -144, 96, 48
                                        Win 10 32 bit
                                        Rod
                                        I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

                                        Comment

                                        Working...
                                        X