Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Возврат значений функциями типа String

7
04 октября 2007 года
@pixo $oft
3.4K / / 20.09.2006
Почему,когда в функции из DLL в EAX загоняется адрес строки(ANSI),при присвоении её значения строковоё переменной в VB происходит критическая ошибка?Ведь VB-строки(вернее,переменная,описанная как строка)-это адрес реальной строки в памяти!?
Выглядит это примерно так:
1)функция MapFile из DLL(открывает файл,выделяет память,равную его размеру,и считывает его туда):
Код:
Invoke CreateFile,[ESP+28],...
Mov hFile,EAX
...
Invoke GetFileSize,EAX,0
Mov dwLen,EAX
Invoke HeapAlloc,hHeap,Heap_Zero_Memory,EAX
Mov lpMem,EAX
...
Invoke ReadFile,hFile,lpMem,dwLen,...
...
Mov EAX,lpMem
Ret 4

2)В VB:
 
Код:
Private Declare Function MapFile Lib "..."(ByVal szFileName As String) As String
...
S=MapFile(...)

Так вот,при таком раскладе вылезает "Программа выполнила недопустимую ошибку",модуль Kernel32.dll(очевидимо,строка копируется с помощью RtlMoveMemory).НО!Если я опишу функцию как Long,то результат вполне нормален(указатель на выделенную память).В чём дело?
Кстати,для освобождения памяти тоже есть функция.И обработку ошибок я опустил для упрощения
2.9K
04 октября 2007 года
Ation
96 / / 27.07.2004
Ret 4 ?
7
04 октября 2007 года
@pixo $oft
3.4K / / 20.09.2006
А што!?Сколько параметров принимает функция?Сколько байт они занимают?
2.9K
04 октября 2007 года
Ation
96 / / 27.07.2004
мда, прогнал :/
Наверно все дело в том, что это не просто указатель на строку.
http://av-school.ru/wiki/index.php/FAQ:VB:Сущность_строк_в_Visual_Basic
Скорее всего кто-то где-то обращается к памяти до блока, который ты выделил, ведь компилятор считает, что функция возвращает String.
Других догадок у меня нет :/
534
04 октября 2007 года
HarryAxe
448 / / 19.01.2006
String в VB != указатель на массив символов. Там первым полем длина хранится (4 байта). Если четвёртый байт в файле имеет старшим битом 1 (в частности, это какой-либо символ кириллицы), то получим отрицательную длину строки, а этого VB нам никак простить не может. Меняй тип возвращаемого значения на Byte() или что-нибудь в этом духе.
7
06 октября 2007 года
@pixo $oft
3.4K / / 20.09.2006
А вот и не угадал!Длина строки хранится в 4-х байтах ДО начала самой строки(т.е. (Offset String)-4),как описано на сайте,указанном Ation'ом
Может,дело в том,что VB пытается преобразовать строку в Unicode(его любимую),а дальше-невыделенная область памяти!?Это что получается,в 2 раза больше придётся выделить?
А массив Byte я не могу использовать-мне надо ИМЕННО В СТРОКЕ воспользоваться нечувствительным к регистру поиском,который есть у VB.Так что,предложите в 2 раза больше памяти выделять+4 байта под длину?
А какие-нибудь WinAPI'шки возвращают строковый результат?
5.1K
06 октября 2007 года
12345678
93 / / 16.12.2006
Код:
Invoke CreateFile,[ESP+28],...
Mov hFile,EAX
...
Invoke GetFileSize,EAX,0
Mov dwLen,EAX
Invoke HeapAlloc,hHeap,Heap_Zero_Memory,EAX
[COLOR="Red"]Mov lpMem,EAX
...
Invoke ReadFile,hFile,lpMem,dwLen,...
...
Mov EAX,lpMem[/COLOR]
Ret 4


Ну вы конечно правильно поступаете что динамически выделяете память под полотно байт из файла, но обратите внимание, что по адресу lpMem храниться не полотно байт а путь к нему (он копируется с eax непосредственно по адресу lpMem). Ну а функция ReadFile расчитыват на то, что по адресу lpMem есть много свободного места и смело начинает копировать туда байты из фаайла, но какой же облом, когда оказываеться места по адресу lpMem всего 4 байта :). Тогда процес накрываеться (ибо за адресом lpMem может следовать в данном случае секция в которую запись запрещена или секция кода, в которую не безопасно писать). А для того чтоб такого не было теоретично, с точки зрения ядерной физики, надо писать так (если ето FASM):

 
Код:
Mov lpMem,EAX
...
Invoke ReadFile,hFile,[lpMem],dwLen,...
...
Mov EAX,lpMem


если не ошибаюсь, на деле не проверял.
31K
12 октября 2007 года
Pr0ger
9 / / 06.10.2007
12345678, это MASM.
@pixo $oft, попробуй под дебаггером, там увидишь где и как падает. Если что надо полный код MapFile смотреть.
7
25 октября 2007 года
@pixo $oft
3.4K / / 20.09.2006
Цитата: 12345678
...Ну вы конечно правильно поступаете что динамически выделяете память под полотно байт из файла, но обратите внимание, что по адресу lpMem храниться не полотно байт а путь к нему (он копируется с eax непосредственно по адресу lpMem). Ну а функция ReadFile расчитыват на то, что по адресу lpMem есть много свободного места и смело начинает копировать туда байты из фаайла, но какой же облом, когда оказываеться места по адресу lpMem всего 4 байта :). Тогда процес накрываеться (ибо за адресом lpMem может следовать в данном случае секция в которую запись запрещена или секция кода, в которую не безопасно писать)...


Конечно,мы правильно поступаем,что выделяем динамически память,вот только если мы взглянем в описание ReadFile,то заметим,что там передаётся не сам буфер,а его адрес(хе-хе...передавать буфер,особенно если он в несколько Мб,через стек),так что тут всё нормально
А вот под отладчиком VB-программа не очень хорошо отлаживается-может быть многопоточной(Олькой не отлаживается вовсе) или вызывает кучу некритических ошибок(в смысле,можно продолжить выполнение),да и не в том дело.Упасть программа может,когда ей вздумается-на первом файле,четвёртом и т.д.,в процессе подсматривания за значениями прочитанных строк.Я даже действовал согласно мануалу по созданию VB-строк,любезно выложенному Ation'ом(т.е. выделял на 6 байт больше,пихал в первые 4 байта длину,корректировал указатель на +4 байта)-не помогло.Могу попытаться выложить релиз
Не забывайте!Моя цель-именно строка(дабы в ней можно было искать средствами VB),а не массив байтов и т.д.

534
25 октября 2007 года
HarryAxe
448 / / 19.01.2006
Функция выделения памяти под строки, обслуживаемые атоматизацией:
 
Код:
BSTR SysAllocStringLen(
  const OLECHAR *  pch,
  unsigned int  cch  
);
, либо
 
Код:
BSTR SysAllocStringByteLen(
  LPCSTR  psz,    
  unsigned int  len  
);
для ANSI-строк
Если и это не прокатит, то это может также означать, что подкалывает reference encounting. В таком случае, бросай это гиблое дело и пиши чтение файла на VB. Один хрен, твоя MapFile своего названия не оправдывает...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог