Announcement

Collapse
No announcement yet.

What are Stack and Heap ?

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

  • Mike Doty
    replied
    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

    Leave a comment:


  • Stuart McLachlan
    replied
    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.

    Leave a comment:


  • Mike Doty
    replied
    It is often 24, but I get all sorts of answers.

    Leave a comment:


  • Stuart McLachlan
    replied
    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.

    Leave a comment:


  • Mike Doty
    replied
    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

    Leave a comment:


  • Stuart McLachlan
    replied
    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

    Leave a comment:


  • Stuart McLachlan
    replied
    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
    '

    Leave a comment:


  • Steve Hutchesson
    replied
    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.

    Leave a comment:


  • Jerry Wilson
    replied
    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

    Leave a comment:


  • Steve Hutchesson
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    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."

    Leave a comment:


  • Steve Hutchesson
    replied
    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.

    Leave a comment:


  • Stuart McLachlan
    replied
    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

    Leave a comment:


  • Jerry Wilson
    replied
    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

    Leave a comment:


  • Steve Hutchesson
    replied
    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.

    Leave a comment:


  • Stuart McLachlan
    replied
    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, 07:44 PM.

    Leave a comment:


  • Tim Lakinir
    replied
    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?

    Leave a comment:


  • Tim Lakinir
    started a topic What are Stack and Heap ?

    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.
Working...
X