CRT Aligned Malloc functions

Windows specific questions.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

CRT Aligned Malloc functions

Postby MichaelW » Dec 19, 2013 13:11

I moved this here from this post so it would not end up buried in a mostly-unrelated topic.

For Windows XP (and later AFAIK) the CRT provides a way to allocate an aligned buffer without all of the “monkey motion” involved in having to align the memory and deal with two pointers, and that adds the aligned_offset capability, making it relatively easy to align an arbitrary structure member (and there are probably other uses that have not occurred to me).

This is a quick test of the relevant CRT functions (minus the functions not supported on my Windows XP SP3 systems).

Code: Select all

#include once "crt/stddef.bi"

extern "c"

declare function _aligned_malloc(byval as size_t,byval as size_t)as any ptr
'' parameters: size, alignment

declare function _aligned_realloc(byval as any ptr,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, size, alignment

'' This is apparently not implemented in my Windows XP MSVCRT.DLL or
'' in the corresponding 0.90.1 Win32 import library:
declare function _aligned_recalloc(byval as any ptr,byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, num, size, alignment

declare function _aligned_offset_malloc(byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: size, alignment, offset

declare function _aligned_offset_realloc(byval as any ptr,byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, size, alignment, offset

'' This is apparently not implemented in my Windows XP MSVCRT.DLL or
'' in the corresponding 0.90.1 Win32 import library:
declare function _aligned_offset_recalloc(byval as any ptr,byval as size_t,byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, num, size, alignment, offset

'' This is apparently not implemented in my Windows XP MSVCRT.DLL or
'' in the corresponding 0.90.1 Win32 import library:
declare function _aligned_msize(byval as any ptr,byval as size_t,byval as size_t) as size_t
'' parameters: ptr, alignment, offset

declare sub _aligned_free(byval as any ptr)
'' parameters: ptr

end extern

''------------------------------------------------------------------
'' Returns the largest alignment, or zero if passed a null pointer.
''------------------------------------------------------------------
function alignment naked( byval address as any ptr ) as integer
  asm
    xor eax, eax        '' prep for return zero
    mov ecx, [esp+4]    '' get address parameter
    bsf ecx, ecx        '' scan from bit 0 for first set bit
    jz 0f               '' return if no set bit
    mov eax, 1          '' set bit 0
    shl eax, cl         '' shift left by index of first set bit
  0:
    ret 4               '' return and remove parameter from stack
  end asm
end function

dim as any ptr p

p = _aligned_malloc( 100, 16 )
print hex(p)
print "alignment: ";alignment( p )
p = _aligned_realloc( p, 200, 16 )
print hex(p)

_aligned_free( p )

p = _aligned_offset_malloc( 100, 16, 2 )
print hex( p )
print "alignment: ";alignment( p )
print "alignment: ";alignment( cast(ubyte ptr,p+2) )
p = _aligned_offset_realloc( p, 200, 16, 2)
print "alignment: ";alignment( p )
print "alignment: ";alignment( cast(ubyte ptr,p+2) )

_aligned_free( p )

sleep

Code: Select all

333920
alignment:  32
3339C0
333AAE
alignment:  2
alignment:  16
alignment:  2
alignment:  16

Edit:

Thinking back, I'm not sure that the MSVCRT.DLL on a pre-SP Windows XP would support these functions, but I just checked an SP1 CD and it apparently does support _aligned_malloc, _aligned_realloc, _aligned_offset_malloc, _aligned_offset_realloc, and _aligned_free.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: CRT Aligned Malloc functions

Postby MichaelW » Jul 31, 2015 0:38

Here is a 64-bit version, tested with Version 1.03.0 (07-01-2015):

Code: Select all

#include once "crt/stddef.bi"

extern "c"

declare function _aligned_malloc(byval as size_t,byval as size_t)as any ptr
'' parameters: size, alignment

declare function _aligned_realloc(byval as any ptr,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, size, alignment

declare function _aligned_recalloc(byval as any ptr,byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, num, size, alignment

declare function _aligned_offset_malloc(byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: size, alignment, offset

declare function _aligned_offset_realloc(byval as any ptr,byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, size, alignment, offset

declare function _aligned_offset_recalloc(byval as any ptr,byval as size_t,byval as size_t,byval as size_t,byval as size_t)as any ptr
'' parameters: ptr, num, size, alignment, offset

declare function _aligned_msize(byval as any ptr,byval as size_t,byval as size_t) as size_t
'' parameters: ptr, alignment, offset

declare sub _aligned_free(byval as any ptr)
'' parameters: ptr

end extern

''--------------------------------------------------------------------
'' Returns the largest alignment, or zero if passed a null pointer.
''
'' For the X64 calling convention the first four non-floating-point
'' arguments are passed in RCX, RDX, R8, and R9, and 64-bit
'' integers are returned in RAX.
''--------------------------------------------------------------------
function alignment naked( byval address as any ptr ) as integer
  asm
      xor   rax, rax   '' prep for return zero       
      bsf   rcx, rcx   '' scan RCX for LS set bit, return index in RCX
      jz    0f         '' return if no set bit
      mov   rax, 1     '' set bit 0
      shl   rax, cl    '' shift left by index
  0:
      ret
  end asm
end function

dim as any ptr p

''--------------------------------------------
'' Do a quick test of the alignment function:
''--------------------------------------------

for p = 0 to 32
    print alignment( p )   
next

sleep

''---------------------------------------------------------
'' These tests skip the functions that, to the best of my
'' knowledge, are not supported by the Windows XP MSVCRT.
''---------------------------------------------------------

p = _aligned_malloc( 100, 16 )
print hex(p,16)
print "alignment: ";alignment( p )
p = _aligned_realloc( p, 200, 16 )
print hex(p,16)
print "alignment: ";alignment( p )
_aligned_free( p )

p = _aligned_offset_malloc( 100, 16, 2 )
print hex(p,16)
print "alignment: ";alignment( p )
print "alignment: ";alignment( cast(ubyte ptr,p+2) )
p = _aligned_offset_realloc( p, 200, 16, 3)
print "alignment: ";alignment( p )
print "alignment: ";alignment( cast(ubyte ptr,p+3) )
_aligned_free( p )

sleep

Code: Select all

 0
 1
 2
 1
 4
 1
 2
 1
 8
 1
 2
 1
 4
 1
 2
 1
 16
 1
 2
 1
 4
 1
 2
 1
 8
 1
 2
 1
 4
 1
 2
 1
 32
0000000000175B60
alignment:  32
0000000000175B60
alignment:  32
0000000000175B5E
alignment:  2
alignment:  32
alignment:  1
alignment:  32

Edit: I tried testing _aligned_msize, from a 64-bit app under Windows 8.1-64, and the linker reports it as an undefined reference. After some research it looks like the name should be _msize, and after I changed the name in the declaration and in the call the app linked OK, but when executed the app triggers exception 0xC0000011. I cannot find this exception code in the FreeBASIC headers, but in the PellesC ntstatus.h:

#define STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)

The documentation I find, here, for example, does not make sense because it states that the block must have been allocated by _aligned_malloc or _aligned_realloc, and that the alignment and offset values must be the same as the values passed to these functions, but the functions do not have an offset parameter.

Return to “Windows”

Who is online

Users browsing this forum: No registered users and 4 guests