GlobalAlloc проблема с выделением памяти

Тема в разделе "WASM.BEGINNERS", создана пользователем JCronos, 13 май 2009.

  1. JCronos

    JCronos New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2009
    Сообщения:
    98
    Такой код раньше у меня работал,

    Код (Text):
    1. nvoke   CreateFile, addr szFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING,
    2.                 FILE_ATTRIBUTE_NORMAL, NULL
    3. cmp     eax, -1
    4. jz      _error
    5. mov     hFile, eax
    6.  
    7. invoke      GetFileSize, hFile, NULL
    8. mov         dwSize, eax
    9.    
    10. invoke  GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, dwSize
    11. mov     ebx, eax
    12. mov     hMemory, eax
    13.        
    14. invoke  GlobalLock, hMemory
    15. mov         pMemory, eax
    16.  
    17. invoke      ReadFile, hFile, pMemory, dwSize, NULL, NULL
    После захода в ReadFile вываливается здесь
    Код (Text):
    1. 7C80188E    8901            mov     dword ptr ds:[ecx], eax
    2. 7C801890    33C0            xor     eax, eax
    3. 7C801892    40              inc     eax
    4. 7C801893    E8 730C0000     call    7C80250B                         ; kernel32.7C80250B
    5. 7C801898    C2 1400         retn    14
    6.  
    7.  
    8. eax=000000F2
    9. ds:[00000000]=???
    Подскажите в чем проблема?
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    а что передешь в ридфаел
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Не хватает "LPDWORD lpNumberOfBytesRead".

     
  4. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Параметр ReadFile, определяющий адрес переменной, получающей количество прочитанных байт, опционален только если есть overlapped-параметр. (Параметр: последний-предпоследний).
    Можно предположить, что такой код мог работать на win95.
     
  5. JCronos

    JCronos New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2009
    Сообщения:
    98
    Нужно было LPDWORD lpNumberOfBytesRead указать
    Код (Text):
    1. invoke      ReadFile, hFile, pMemory, dwSize, addr lpbr ,NULL
    Всем спасибо!
     
  6. JCronos

    JCronos New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2009
    Сообщения:
    98
    Еще один вопрос:

    Парсер ищет конец строки равен он CLRF(0Ah и 0Dh), но как быть с концом текстового файла, у него
    тоже есть CLRF, но вот после этих байтов идет мусор, посмотрел в отладчике

    Код (Text):
    1. 00142EEB                                         0D 0A EE               ..о
    2. 00142EFB  FE EE FE EE FE EE FE EE FE EE FE EE FE 00 00 00  юоюоюоюоюоюою...
    (0D 0A - '..') - это CLRF, затем EEh и другой мусор, конечно можно было бы, для конкретного текстового файла искать EEh и FEh и что там еще, но может они не постоянны и будут другими для другого текстового файла, вот в чем проблема.
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    JCronos
    Это мусор не из файла, а из выделенного блока кучи. Причем 0xFEEE это специальная сигнатура, которой заполняются свободные блоки кучи в режиме отладки (хвосты занятых ,блоков заполняются ABAB-ой ;), т.е. у тебя похоже либо память не выделена, либо при чтении произошло переполнение - вылет за пределы выделенного блока.
    А по правильному, нужно выделять память на 1 байт больше размера файла - для записи замыкающего нуля, и либо занулять весь блок при выделении, либо после чтения данных в буфер установить замыкающий ноль ручками по адресу (lpMemory+dwSize).
    PS: В файле замык.ноль не хранится
     
  8. JCronos

    JCronos New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2009
    Сообщения:
    98
    Спасибо leo многое прояснил :)
     
  9. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    leo
    Почему? Сколько выделил, столько и записал из файла. 0D 0E — последние символы файла, а дальше уже кусок невыделенной памяти.
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Т.е.... 0D 0A.
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    l_inc
    Как говориться "учите матчасть" ;)
    Во-первых, в виндовой куче любой блок памяти (и занятый и свободный) имеет свой 8-байтовый заголовок и размер блока также кратен 8 байтам. В первых 4 байтах заголовка хранятся размеры текущего и предыдущего блоков памяти в 8-байтовых единицах, причем макс.размер блока кучи (специально) ограничен значением < 0xFEEE*8 и поэтому первые 4 байта заголовка не могут быть равны 0xFEEEFEEE.
    Во-вторых, в режиме отладки для контроля целостности кучи под занятый блок выделяется памяти на 8 байт больше и хвостовые байты в блоке заполняются контрольной сигнатурой 0xABAB. Соот-но свободные блоки также имеют 8-байтовый заголовок и заполнены сигнатурой 0xFEEE.
    В-третьих, менеджер кучи запрашивает память у винды обычным VirtualAlloc-ом и соотв-но текущий размер памяти кучи всегда кратен 4К. Поэтому вслед за выделенным блоком всегда должен идти либо сводный или занятый блок со своим заголовком (не содержащим 0xFEEE), либо невыделенная память, если этот занятый блок "каким-то чудом" точно вписался в конец последней выделенной страницы.

    Вывод:
    Если бы памяти было бы выделено ровно столько, сколько в нее записано данных, то вслед за замыкающими байтами 0D 0A должна была идти сигнатура 0xABAB и затем заголовок следующего блока (не содержащий 0xFEEE). Поэтому ситуация, приведенная в #6, возможна только в двух случаях:
    1) Под блок было выделено памяти как минимум на 16 байт больше, чем реально в него записано. Поэтому 0xFEEE это мусор, оставшийся от ранее свободного блока, а хвостовая сигнатура 0xABAB и заголовок следующего блока идут где-то дальше
    2) При записи данных произошло переполнение и вылет на середину следующего блока