Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.117.8.216] |
|
Сообщ.
#1
,
|
|
|
Есть функция в DLL, описанная в моей программе как
var ShareInfo: function(const WhatInfo: Cardinal): PChar; DLL грузится динамически, функция ShareInfo() в DLL находится корректно (GetProcAddress() возвращает <> nil). Далее, при выполнении следующий строки кода Label8.Caption := StrPas(ShareInfo(1)); <либо> Label8.Caption := String(ShareInfo(1)); <либо даже так> Label8.Caption := ShareInfo(1); программа закрывается без всяких сообщений об ошибке и т.п. Это если запускать без дебаггера. Если с ним, то имеем: "Project <путь_к_exe> faulted with message 'access violation at 0x00403e4c: write of address 0x0045216b'." Опытным путем доказано, что ошибка происходит при конвертировании null-terminated строки (PAnsiChar aka PChar) в паскалевкую произвольной длины (String). Используем Delphi 7. Что делать и как быть? |
Сообщ.
#2
,
|
|
|
Savant, покажи код функции. Но вероятней всего в функциях просто не выделяется память под PChar.
|
Сообщ.
#3
,
|
|
|
Естественно проблемы с памятью. Щас придет Jack128 и раскритикует это дело
|
Сообщ.
#4
,
|
|
|
Естественно раскритикую.
Где память выделется под Pchar ?? С такой сигнатурой функции Цитата Savant @ function(const WhatInfo: Cardinal): PChar; память может выделятся только в самой функции, что не есть хорошо. Смотрим в качестве примера WinAPI. Банальный пример GetWindowText. Эта функция тоже должна вернуть строку, только вот память под эту строку выделяет не сама GetWindowText , а её клиент. И тебе тоже нужно сделать аналогично. function ShareInfo(const WhatInfo: Cardinal; Buf: PChar; BufSize: Cardinal): Integer; Buf - буфер, в который фнукция вернет информацию. BufSize - размер функции. Результат функции - сколько реально байт занимает возращенная информация. Так же в WinAPI принято, что если в качестве параметра Buf передан nil, то функция должна вернуть необходимый размер буффера. И вызывать ты будешь эту функцию примерно так var BufSize: Integer; Buf: Pchar; begin BufSize := ShareInfo(WhatInfo, nil, 0); GetMem(Buf, BufSize); try ShareInfo(Buf, BufSize); ... finally FreeMem(Buf); end; end; |
Сообщ.
#5
,
|
|
|
jack128
Ну допустим переделаем все как Вы предлагаете, но ведь все равно не работает . Это код в DLL: function ShareInfo(const WhatInfo: Integer; Buf: PChar; const BufSize: Integer): Integer; stdcall; const info: array[1..3] of String = ('abc', 'def', 'xyz123'); begin MessageBox(0, PChar(Format('%d', [WhatInfo])), 'ShareInfo() execution', 0); case WhatInfo of 1..3: begin Result := Length(info[WhatInfo]) + 1; // учитываем '\0' в конце if Buf <> nil then begin if BufSize >= Result then begin if lstrcpyn(Buf, @info[WhatInfo], Result) = nil then Result := -2; // неудача записи end else Result := -1; // маленький буфер end else begin { Возвращаем нужный размер, инициализация Result парой строчек выше } end; end else // Ошибочное значение параметра WhatInfo Result := 0; end; end; А это вызов в программе: var ShareInfo: function (const WhatInfo: Integer; Buf: PChar; const BufSize: Integer): Integer; var BufSize: Integer; Buf: PChar; begin .... BufSize := ShareInfo(1, nil, 0); MessageBox(0, PChar(Format('%d', [BufSize])), nil, 0); GetMem(Buf, BufSize); try ShareInfo(1, Buf, BufSize); Label8.Caption := String(Buf); finally FreeMem(Buf); end; Кстати говоря, с помощью MessageBox'a в функции DLL выяснилось, что параметр WhatInfo в процессе передачи несколько искажается, в частности при первом вызове (ShareInfo(1, nil, 0)) он принимает значение 1243372 (причем при любом значении WhatInfo), а при втором (ShareInfo(1, Buf, BufSize)) - 1242508 (если WhatInfo передается как константа) или 1242512 (если как переменная). Cмахивает на адреса в памяти... Кто-нибудь въехал ? |
Сообщ.
#6
,
|
|
|
Цитата Savant @ stdcall; var ShareInfo: function (const WhatInfo: Integer; Buf: PChar; const BufSize: Integer): Integer; |