Выделение локальной памяти AllocMem, ReallocMem

Дата публикации 18 янв 2024 | Редактировалось 8 фев 2024
Кто хочет излечить нашу современность программирования от ее внутренних болезней,
от всего ее гнилья, тот прежде всего должен иметь смелость взглянуть правде в лицо и найти причины болезни. (с)

Код (Text):
  1. #include <windows.h>
  2.  
  3. #ifdef _DEBUG
  4.  
  5. LPVOID AllocMem( DWORD cb )
  6.  
  7. {
  8.     LPDWORD  pMem;
  9.     DWORD    cbNew;
  10.  
  11.     cbNew = cb + 2 * sizeof( DWORD );
  12.  
  13.     if( cbNew & 3 )
  14.         cbNew += sizeof( DWORD ) - ( cbNew & 3 );
  15.  
  16.     pMem = (LPDWORD)LocalAlloc (LPTR | LMEM_ZEROINIT, cbNew );
  17.  
  18.     if( !pMem )
  19.     {
  20.         DPF0( "LocalAlloc failed.\n" );
  21.         return NULL;
  22.     }
  23.  
  24.     *pMem=cb;
  25.  
  26.     *(LPDWORD)( (LPBYTE)pMem + cbNew - sizeof( DWORD ) ) = 0xdeadbeef;
  27.  
  28.     DPF0( "Allocated %d bytes @%08x\n", cbNew, pMem );
  29.  
  30.     return (LPVOID)( pMem + 1 );
  31. }
  32.  
  33.  
  34. VOID FreeMem( LPVOID pMem, DWORD cb )
  35. {
  36.     DWORD   cbNew;
  37.     LPDWORD pNewMem;
  38.  
  39.     if( !pMem )
  40.         return;
  41.  
  42.     pNewMem = pMem;
  43.     pNewMem--;
  44.  
  45.     cbNew = *pNewMem + 2 * sizeof( DWORD );
  46.  
  47.     if( cbNew & 3 )
  48.         cbNew += sizeof( DWORD ) - ( cbNew & 3 );
  49.  
  50.     /* Check that the size the caller thinks the block is tallies with
  51.      * the size we placed before beginning of the block, and that the
  52.      * end of the block has our signature:
  53.      */
  54.     if( ( cb && ( *pNewMem != cb ) ) || /* If cb == 0, don't worry about this check */
  55.       ( *(LPDWORD)( (LPBYTE)pNewMem + cbNew - sizeof( DWORD ) ) != 0xdeadbeef ) )
  56.     {
  57.         DPF0( "Corrupt Memory detected freeing block: %0lx\n", pNewMem );
  58. #ifdef DEBUG
  59.         DebugBreak();
  60. #endif
  61.     }
  62.  
  63.     memset( pNewMem, 0xFE, cbNew );   // Mark frEEd blocks
  64.  
  65.     DPF0( "Freed %d bytes @%08x\n", cbNew, pNewMem );
  66.  
  67.     LocalFree((HANDLE) pNewMem );
  68. }
  69.  
  70.  
  71. LPVOID ReallocMem( LPVOID lpOldMem, DWORD cbOld, DWORD cbNew )
  72. {
  73.     LPVOID lpNewMem;
  74.  
  75.     lpNewMem = AllocMem( cbNew );
  76.  
  77.     if( lpOldMem )
  78.     {
  79.         if( lpNewMem )
  80.         {
  81.             memcpy( lpNewMem, lpOldMem, min( cbNew, cbOld ) );
  82.         }
  83.  
  84.         FreeMem( lpOldMem, cbOld );
  85.     }
  86.  
  87.     return lpNewMem;
  88. }
  89.  
  90. #endif // debug
  91.  
  92.  
  93. LPTSTR AllocStr( LPTSTR lpStr )
  94.  
  95. /*++
  96.  
  97. Routine Description:
  98.  
  99.     This function will allocate enough local memory to store the specified
  100.     string, and copy that string to the allocated memory
  101.  
  102. Arguments:
  103.  
  104.     lpStr - Pointer to the string that needs to be allocated and stored
  105.  
  106. Return Value:
  107.  
  108.     NON-NULL - A pointer to the allocated memory containing the string
  109.  
  110.     FALSE/NULL - The operation failed. Extended error status is available
  111.         using GetLastError.
  112.  
  113. --*/
  114.  
  115. {
  116.     LPTSTR lpMem;
  117.  
  118.     if( !lpStr )
  119.         return NULL;
  120.  
  121.     lpMem = AllocMem( STRING_BYTE_COUNT( lpStr ) );
  122.  
  123.     if( lpMem )
  124.         lstrcpy( lpMem, lpStr );
  125.  
  126.     return lpMem;
  127. }
  128.  
  129.  
  130. VOID ReallocStr( LPTSTR *plpStr, LPTSTR lpStr )
  131. {
  132.     FreeStr( *plpStr );
  133.     *plpStr = AllocStr( lpStr );
  134. }
  135.  
  136.  
  137. VOID FreeStr( LPTSTR lpStr )
  138. {
  139.     FreeMem( lpStr, STRING_BYTE_COUNT( lpStr ) );
  140. }
  141.  

2 565
Research

Research
Member

Регистрация:
6 янв 2024
Публикаций:
1

Комментарии


      1. Research 18 янв 2024
        Да можно заменить на HeapAlloc, глаз - алмаз

        Не использовать WinAPI? Пфф..)
      2. MaKsIm 18 янв 2024
        Если лечим от гнилья, тогда что тут делает древняя и забытая LocalAlloc, оставшаяся со времен разделения адресного пространства на сегменты? Почему не HeapAlloc?

        При изменении размера вы принудительно копируете блоки из одной памяти в другую, даже если системный менеджер памяти может просто изменить размер вашего блока для уменьшения (что точно не требует лишнего копирования) или увеличения объема. Где же тут избавление от причин болезни. Как минимум при уменьшении размера блока вы можете и сами просто подвинуть свой маркер переполнения блока чуть ближе, записать новый размер в начало блока и вызвать системную функцию.

        И самое главное это использование WinAPI - о переносимости такой программы можно забыть. Это наихудшая причина болезни.