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
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...
For an unknown reason VirtualQuery only works with MEMORY_BASIC_INFORMATION as a LOCAL, I've dealt with this issue before...
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 ?...
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
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
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
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.
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...
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
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
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]
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
-
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.