News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Virtual Mem functions - some questions

Started by Rainstorm, August 31, 2008, 01:23:51 PM

Previous topic - Next topic

Rainstorm

Hi

I usually use the HeapFunctions when i need to reallocate & its easy there.
How would i reallocate Memory with VirtualAlloc ? - Is this usually done ?
or would it mean.. just allocating a new buffer - then copying the data from the old buffer into the new one - and finally Freeing the old buffer ?

============

here's some code am having a prob with. It doesn't involve reallocation but the size from VirtualQuery is returned as 0.

both the return val in eax & the size member of the structure return 0 - I have checked the size supplied in VirtualAlloc just before the call & its not 0.

.data
    mem_sizeinfo    MEMORY_BASIC_INFORMATION    <0>

.code

    invoke VirtualAlloc, NULL, edx, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
        cmp eax, NULL
        je mem_allocation_error
        mov p_destbuff, eax
    invoke VirtualQuery, p_destbuff, addr mem_sizeinfo, sizeof mem_sizeinfo
;        mov destbuff_size, eax
     
        mov edx, mem_sizeinfo.RegionSize
        mov destbuff_size, edx


    pushad
    pushfd
    print ustr$(destbuff_size)," - buff size",13,10
    popfd
    popad



evlncrn8

reallocation with virtual alloc isn't easy..
you would have to make another block bigger than the first one and copy the data to it, then free the first block..
virtualalloc etc.. are not designed for resizing etc like global/heap api's...

DoomyD

For an unknown reason VirtualQuery only works with MEMORY_BASIC_INFORMATION as a LOCAL, I've dealt with this issue before...


evlncrn8

Quote from: DoomyD on September 01, 2008, 05:44:25 AM
For an unknown reason VirtualQuery only works with MEMORY_BASIC_INFORMATION as a LOCAL, I've dealt with this issue before...



possibly it requires alignment of 4 ?...

Rainstorm

evlncrn8, thx for the confirmation on that. - that would be a real pain. -i've used the heap functions for the most part before this & never had a problem with those.

DoomyD,
   i was at a loss after a while of spending quite some time trying to figure it out.
what does "works with MEMORY_BASIC_INFORMATION as a LOCAL," mean exactly ?
my primary reason was to get the size commited, but i think.. the size allocated by virtualalloc is very close to the size specified.. & maybe i can safely assume the size i specified has been allocated. (correct me if am wrong)

thanks for the feedback

Rainstorm

Rainstorm

elvncrn8 wrote
Quotepossibly it requires alignment of 4 ?...
i shifted, my structure to the top as the 1st item in the .data section after reading your post & tried. all the members are dword members too in the struct. - it now returns a valid size, so that may be it.
from what i calculated it should return around 3172 as the size, it returns 4096.
Still it returns some size as compared to before when it was always returning 0

        mov edx, edi                       
        sub edx, p_coll_buff   ; (end pointer - beginning pointer) =1124

        pushad
        pushfd
        print ustr$(edx)," - edx ",13,10  ; this returns 1124
        popfd
        popad

        add edx, 2048               ; 2048 + 1124 = 3172

    invoke VirtualAlloc, NULL, edx, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
        cmp eax, NULL
        je mem_allocation_error
        mov p_destbuff, eax
    invoke VirtualQuery, p_destbuff, addr mem_sizeinfo, sizeof mem_sizeinfo

        mov edx, mem_sizeinfo.RegionSize
        mov destbuff_size, edx                 ;  ; returns 4096

        pushad
        pushfd
        print ustr$(destbuff_size)," - buff size",13,10   ; returns 4096
        popfd
        popad


MichaelW

Windows expects data to be aligned as the C/C++ compilers would align it.

QuoteInter-structure/union alignment is the simpler case. The rule here is that the compiler aligns the structure with the largest alignment requirement of any of the members of the structure.

http://msdn.microsoft.com/en-us/library/aa290049.aspx

eschew obfuscation

Tedd

VirtualAlloc allocates whole pages, so whatever size you request will be rounded up to the next page - usually this will be 4kB, but you should really check through GetSystemInfo.

HeapReAlloc will expand the current memory region if there is free space following it, or allocate a larger region and copy the old data into it.

To do your own reallocation, you could try to allocate the next page following the region you already have and if that's successful then you can just 'overflow' into that memory, if not you'll have to allocate a new larger space and copy the data.
No snowflake in an avalanche feels responsible.

evlncrn8

Quoteinvoke VirtualAlloc, NULL, edx, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE

MEM_COMMIT or MEM_RESERVE has caused me problems before...

MEM_COMMIT   Allocates physical storage in memory or in the paging file on disk for the specified region of pages.
An attempt to commit an already committed page will not cause the function to fail. This means that a range of committed or decommitted pages can be committed without having to worry about a failure.

MEM_RESERVE   Reserves a range of the process's virtual address space without allocating any physical storage. The reserved range cannot be used by any other allocation operations (the malloc function, the LocalAlloc function, and so on) until it is released. Reserved pages can be committed in subsequent calls to the VirtualAlloc function.

so the usage of those 2 combined sort of contradict each other...
because commit sort of reserves it too...


Rainstorm

Hiya Tedd,
  thanks for the tips & info.
until now i've almost always used HeapRealloc for reallocation

QuoteTo do your own reallocation, you could try to allocate the next page following the region you already have and if that's successful then you can just 'overflow' into that memory,
was wondering about that, thx for the confirmation, good to know its okay to do.

evlncrn8, in the windows help.. that what they advise you to do if you wanna reserve & commit in one go, that is,..use MEM_COMMIT or MEM_RESERVE   

Michael, thanks for the link

Rainstorm

Michael wrote..
QuoteWindows expects data to be aligned as the C/C++ compilers would align it.
just using this structure as an example
that structure is filled up by windows.. so does windos take care of the alignment in that case ? because the 2 byte strings in between, szDescription & szSystemStatus could spoil the alignment right ?

thankyou.
--
WSADATA STRUCT
  wVersion      WORD      ?
  wHighVersion  WORD      ?
  szDescription BYTE WSADESCRIPTION_LEN + 1 dup (?)
  szSystemStatus  BYTE WSASYS_STATUS_LEN + 1 dup (?)
  iMaxSockets   WORD      ?
  iMaxUdpDg     WORD      ?
  lpVendorInfo  DWORD      ?
WSADATA ENDS

MichaelW

The attachment contains a quick and dirty C program that shows how the compiler aligns the WSADATA members, compiled with the Microsoft Visual C++ Toolkit 2003. This is the output:

sizeof(wsd)                : 400
sizeof(wsd.wVersion)       : 2
sizeof(wsd.wHighVersion)   : 2
sizeof(wsd.szDescription)  : 257
sizeof(wsd.szSystemStatus) : 129
sizeof(wsd.iMaxSockets)    : 2
sizeof(wsd.iMaxUdpDg)      : 2
sizeof(wsd.lpVendorInfo)   : 4

&wsd.wVersion              : 1244500
&wsd.wHighVersion          : 1244502
&wsd.szDescription[0]      : 1244504
&wsd.szSystemStatus[0]     : 1244761
&wsd.iMaxSockets           : 1244890
&wsd.iMaxUdpDg             : 1244892
&wsd.lpVendorInfo          : 1244896


It looks like Microsoft set the string sizes to eliminate the need for alignment padding following the strings, so the only padding required is 2 bytes following the iMaxUdpDg member to place the lpVendorInfo member at the correct 4-byte alignment. If your code is allocating the structure then you will need to ensure that the structure size and the alignments match what the compiler did.


[attachment deleted by admin]
eschew obfuscation

Rainstorm

maybe the compiler just sees WORD & inserts some padding.. because there are 2 words there..(iMaxSockets and iMaxUdpDg) & the alignment sort of gets adjusted before the last member(lpVendorInfo) which is a DWORD, dunno.

thanks for the info
-

MichaelW

QuoteIntra-structure alignment works by the principle that the members are aligned by the compiler at their natural boundaries, and it does this through padding, inserting as much padding as necessary up to the padding limit.

The natural boundary for a DWORD is 4 bytes, for a WORD 2 bytes, and for a BYTE 1 byte. An address is N-byte aligned if it can be evenly divided by N (i.e. no remainder). All of the WORD addresses can be evenly divided by 2. The next address after the iMaxUdpDg member is 1244894 which cannot be evenly divided by 4, but after padding the address becomes 1244896, which can be evenly divided by 4.
eschew obfuscation