Странный Acess Violetion

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Странный Acess Violetion

Сообщение IDIV » 13.07.2006 19:47:57

написал такую процедуру:
Код: Выделить всё
procedure MakeInterface(nameOfFile:pchar);
label loop;
var
hand:handle;
size:dword;
readed:dword;
buff:^byte;
i:integer;
begin
buff:=pbyte(0);
hand:=CreateFile(nameOfFile,GENERIC_READ,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
buff:=LocalLock(LocalAlloc(LPTR,GetFileSize(hand,nil)+1));
if buff=nil then begin
MessageBox(0,'Can"t allocate memory','ERROR',0);
ExitProcess(0);
end;
ReadFile(hand,buff,GetFileSize(hand,nil),readed,nil);
MessageBox(0,'suc','suc',0);
i:=0;
loop:
while buff[i]<>$24 do begin
MessageBox(0,'lup','lup',0);
if buff[i]=$0D then begin
buff[i]:=0;
buff[i+1]:=0;
i+=2;
goto loop;
end;
i+=1;
end;
end;

при обращении к ней происходит AV.Ну чтож, загружаю отладчик и смотрю что не так.Оказалась ошибка тут-while buff[i]<>$24 do begin, компилятор сгенерировал такой код
00500F7F |> 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14];ebp-14-адрес начала выделеной памяти
00500F82 |. 8B45 E8 |MOV EAX,DWORD PTR SS:[EBP-18];это i
00500F85 |. 0FB60402 |MOVZX EAX,BYTE PTR DS:[EDX+EAX]
Я обратился к указателю здесь, как в С, но похоже надо как-то подругому.Просветите пожалуйста.
Последний раз редактировалось IDIV 13.07.2006 21:01:36, всего редактировалось 1 раз.
IDIV
незнакомец
 
Сообщения: 4
Зарегистрирован: 13.07.2006 19:36:03

Сообщение ev » 13.07.2006 20:46:53

читать неформатированный код довольно сложно :(
уж не говоря о том, как сложно в нем разобраться ...
ev
долгожитель
 
Сообщения: 1764
Зарегистрирован: 27.04.2005 23:19:06
Откуда: Москва

Сообщение SovNarKom » 13.07.2006 21:41:48

IDIV
Код - жесткач, для начала buff^[i], хотя это врятли принципиально...
Что-то с размером буфера не то, тут бы код в нормальный вид привести, без всяких goto loop;

LocalLock... это как я понимаю винапишная функция, хачем она тут?
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение @lex » 14.07.2006 12:21:19

Попробуй выражения при if, while и т.п. брать в скобки, всмысле так:
while (buff[i]<>$24) ...
Незнаю как FP, но старый TP иногда из-за этого начинал генерировать рандомные ошибки. :)
@lex
постоялец
 
Сообщения: 180
Зарегистрирован: 19.06.2006 13:16:29
Откуда: Невинномысск

Сообщение IDIV » 14.07.2006 17:05:40

SovNarKom
С размером буфера все в порядке вроде. Просто компилятор генерирует код как будто я обращаюсь к указателю на указатель.По идее он должен делать что-то вроде :
Код: Выделить всё
mov edx, ebp-14;
mov ebx, ebp-18;
movzx eax, byte ptr ds:[edx+ebx];

то что генерит FP, я приводил выше.
А винапи здесь потому-что паскаль я использую только для создания интерфейса начал учить недели две назад и плохо знаю его библиотеки.Сответственно для работы с памятью юзаю винапи.
IDIV
незнакомец
 
Сообщения: 4
Зарегистрирован: 13.07.2006 19:36:03

Сообщение Sergei I. Gorelkin » 14.07.2006 17:43:52

Ассемблерный код генерится нормально... EBP - указатель на область стека, относительно него ведется доступ к локальным переменным. Переменная buff - сама является указателем.

Другое дело - ф-ция ReadFile, возможно ее надо вызывать так:
Код: Выделить всё
ReadFile(hand, buff^, ....);
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение IDIV » 14.07.2006 18:33:17

Sergei I. Gorelkin
Действительно.Спасибо за помощ, но я только не понял.Я объявил buff, как указатель, а buff^ это разименование указателя.Это получается, что я читаю данные по адресу хранящемуся в памяти по адресу записанному в buff.По-моему странно.Или я не прав.
Я строю свои догатки на основе знания С так что не обессудте.Просто там бы я делал так:
Код: Выделить всё
buff=LocalLock(LocalAlloc(LPTR,100));
ReadFile(hand,buff,GetFileSize(hand,NULL),readed,NULL);
IDIV
незнакомец
 
Сообщения: 4
Зарегистрирован: 13.07.2006 19:36:03

Сообщение Sergei I. Gorelkin » 14.07.2006 19:27:38

Логично, данные читаются по адресу, хранящемуся в buff.
В Паскале присутствует изрядная путаница, вызванная наличием формальных параметров (в Си их нет). В то же время многие исходники просто переведены с Си. В частности, ф-ция ReadFile объявлена так:
Код: Выделить всё
function ReadFile(hFile: THandle; var Buffer; ...);

А ее ближайший родственник - ReadFileEx - вот так:
Код: Выделить всё
function ReadFileEx(hFile: THandle; lpBuffer: LPVOID; ...);


Собственно, ReadFileEx выглядит и вызывается точно так же, как в Си, т.е. указатель передается по значению. А в ReadFile всегда передается адрес переменной, даже если переменная является указателем (в этом и состоит польза формальных параметров - не нужно приводить типы и использовать оператор '@'). Но, чтобы передать значение указателя, надо его разименовать...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение IDIV » 15.07.2006 13:28:02

Sergei I. Gorelkin
Спасибо, всё понял.
IDIV
незнакомец
 
Сообщения: 4
Зарегистрирован: 13.07.2006 19:36:03


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 33

Рейтинг@Mail.ru