Возврат значений функциями типа String
Выглядит это примерно так:
1)функция MapFile из DLL(открывает файл,выделяет память,равную его размеру,и считывает его туда):
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:
...
S=MapFile(...)
Так вот,при таком раскладе вылезает "Программа выполнила недопустимую ошибку",модуль Kernel32.dll(очевидимо,строка копируется с помощью RtlMoveMemory).НО!Если я опишу функцию как Long,то результат вполне нормален(указатель на выделенную память).В чём дело?
Кстати,для освобождения памяти тоже есть функция.И обработку ошибок я опустил для упрощения
Наверно все дело в том, что это не просто указатель на строку.
http://av-school.ru/wiki/index.php/FAQ:VB:Сущность_строк_в_Visual_Basic
Скорее всего кто-то где-то обращается к памяти до блока, который ты выделил, ведь компилятор считает, что функция возвращает String.
Других догадок у меня нет :/
Может,дело в том,что VB пытается преобразовать строку в Unicode(его любимую),а дальше-невыделенная область памяти!?Это что получается,в 2 раза больше придётся выделить?
А массив Byte я не могу использовать-мне надо ИМЕННО В СТРОКЕ воспользоваться нечувствительным к регистру поиском,который есть у VB.Так что,предложите в 2 раза больше памяти выделять+4 байта под длину?
А какие-нибудь WinAPI'шки возвращают строковый результат?
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):
...
Invoke ReadFile,hFile,[lpMem],dwLen,...
...
Mov EAX,lpMem
если не ошибаюсь, на деле не проверял.
@pixo $oft, попробуй под дебаггером, там увидишь где и как падает. Если что надо полный код MapFile смотреть.
Конечно,мы правильно поступаем,что выделяем динамически память,вот только если мы взглянем в описание ReadFile,то заметим,что там передаётся не сам буфер,а его адрес(хе-хе...передавать буфер,особенно если он в несколько Мб,через стек),так что тут всё нормально
А вот под отладчиком VB-программа не очень хорошо отлаживается-может быть многопоточной(Олькой не отлаживается вовсе) или вызывает кучу некритических ошибок(в смысле,можно продолжить выполнение),да и не в том дело.Упасть программа может,когда ей вздумается-на первом файле,четвёртом и т.д.,в процессе подсматривания за значениями прочитанных строк.Я даже действовал согласно мануалу по созданию VB-строк,любезно выложенному Ation'ом(т.е. выделял на 6 байт больше,пихал в первые 4 байта длину,корректировал указатель на +4 байта)-не помогло.Могу попытаться выложить релиз
Не забывайте!Моя цель-именно строка(дабы в ней можно было искать средствами VB),а не массив байтов и т.д.
const OLECHAR * pch,
unsigned int cch
);
LPCSTR psz,
unsigned int len
);
Если и это не прокатит, то это может также означать, что подкалывает reference encounting. В таком случае, бросай это гиблое дело и пиши чтение файла на VB. Один хрен, твоя MapFile своего названия не оправдывает...