Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.01.27;
Скачать: [xml.tar.bz2];

Вниз

STRING DLL   Найти похожие ветки 

 
savyhinst ©   (2007-12-21 19:37) [0]

Здраствуйте.
Как сделать ДЛЛ, чтобы в ней была функция, которая возвращает строку. Вроде, всё просто, но на мысли наталкивает текст в начале ДЛЛ типа нельзя пользоваться строками string без sharemem и borlandMM. Как обойтись без них?
Спасибо за внимание.


 
Германн ©   (2007-12-21 19:39) [1]


> Как обойтись без них?

Забыть про String и использовать PChar.


 
savyhinst ©   (2007-12-21 19:40) [2]

А как корректно использовать PChar? Вроде там не всё гладко. Я вот, например, как-то пробовал...


 
clickmaker ©   (2007-12-21 19:41) [3]


> Я вот, например, как-то пробовал...

я вот тоже как-то пробовал коньяк с пивом смешать... башка болела утром!


 
savyhinst ©   (2007-12-21 19:46) [4]

Ну это понятно. А как использовать PChar? Тут без ограничений?


 
Германн ©   (2007-12-21 19:47) [5]


> Вроде там не всё гладко.

Нигде может быть не гладко, если руки кривые. Других проблем нет.


 
savyhinst ©   (2007-12-21 19:49) [6]

А можно создать работоспособную функцию, которая возвращает PChar?


 
Германн ©   (2007-12-21 19:50) [7]


> А можно создать работоспособную функцию, которая возвращает
> PChar?
>

Можно. WinAPI просто завалена такими функциями.


 
savyhinst ©   (2007-12-21 19:53) [8]

А можно ещё маленький вопросик: как безопаснее сделать: передавать PChar или array of char?


 
Германн ©   (2007-12-21 19:55) [9]

А причем тут безопасность?


 
savyhinst ©   (2007-12-21 19:59) [10]


> А причем тут безопасность?


Чтобы не возникало AcceessViolation att addrreess. Как это всегда бывает.


 
Германн ©   (2007-12-21 20:01) [11]


> Чтобы не возникало AcceessViolation att addrreess. Как это
> всегда бывает.

Тогда без разницы что использовать. Результат то неизбежен. AV :)


 
Григорьев Антон ©   (2007-12-21 20:39) [12]

С WideString никаких проблем - просто берёшь и используешь без всяких ShareMem. Если не жалко терять время на перекодировку ANSI<->Unicode.

А проблема возникает не из-за строк самих по себе, а из-за того, что по умолчанию программа и DLL использует каждая свой менеджер памяти. И ошибки лезут тогда, когда один менеджер памяти пытается освободить то, что выделено другим менеджером. И с PChar будет та же проблема, если, скажем, StrNew вызвать в DLL, а StrDispose - в программе. Просто со string"ом эта проблема наименее предсказуема, так как не всегда очевидно, в какой именно момент будет предпринята попытка освободить память. ShareMem - это интерфейс к менеджеру памяти, который находится в borlndmm.dll. Если подключить ShareMem, то вместо обычного менеджера памяти будет использоваться этот, т.е. один и тот же и для приложения, и для DLL, и проблем, соответственно, не возникнет.

А в новых версиях Delphi есть ещё SimpleShareMem. Считайте, то же самое, только borlndmm.dll за собой таскать не надо. Суть в том, что там расшаривается менеджер памяти того модуля, который загрузился первым, а все остальные, кто подключил SimpleShareMem, вместо своего менеджера памяти будут использовать расшареный. Опять все пользуются оним менджером памяти, проблем нет.

Что же касается WideString, то для строк этого типа память выделяется специальным системным менджером памяти (через функции SysAllocString, SysFreeString и т.п.), и этот менеджер, естественно, один на весь процесс. Так что при использовании WideString вообще без разницы, подключен ShareMem или нет - всё равно дельфийский менеджер памяти не используется.

Но если вы твёрдо решили использовать PChar без ShareMem, для этого есть три варианта:

1. Программа заранее резервирует память для строки, передаёт в DLL указатель на эту память и размер блока, а DLL только заполняет эту строку символами, не перераспределяя память. Освобождается этот блок тоже в основной программе.

2. DLL выделяет память с помощю StrNew. Приложение только читает эту строку, но для освобождения памяти вызывает специальную функцию той же DLL, которая освобождает строку через StrDispose. Получается, что и выделяется, и освобождается память через один и тот же менеджер памяти DLL.

3. Использовать для выделения и освобождения памяти под строку тот же системный менеджер памяти, что и для WideString. Он доступен через функции CoTaskMemAlloc, CoTaskMemFree.


 
savyhinst ©   (2007-12-21 20:41) [13]


> Григорьев Антон ©   (21.12.07 20:39) [12]

Спасибо за исчерпывающий комментарий.


 
Sairex ©   (2007-12-22 11:11) [14]

Ну можно и по другому сделать. Вот пример

Экзешник.
........................
Var P:PChar; S:String;
begin
S:="Мой текст!";
GetMem(P,1024);
lstrcpy(p,S);
MyProcDll(p);
ShowMessage(p);
FreeMem(P);
end;
Дллька.
library MyDll;
uses Windows,SysUtils,Classes; Dialogs;
procedure MyProcDll(P:PChar);
Var S:String; P:PChar;
begin
ShowMessage(P);
Lstrcpy(P,PChar("My Text..."));
end;
end.

Данный НАПИСАННЫЙ код я не проверял на работу. А так достаточно часто использую такой подход для передачи данных из\в длл.

Помоему эт реализация п.1
1. Программа заранее резервирует память для строки, передаёт в DLL указатель на эту память и размер блока, а DLL только заполняет эту строку символами, не перераспределяя память. Освобождается этот блок тоже в основной программе.


 
DiamondShark ©   (2007-12-22 22:00) [15]


> GetMem(P,1024);
> lstrcpy(p,S);
> MyProcDll(p);

Вот так и появлятся программы, которые атакуются методом переполнения буфера.


 
Dimaxx ©   (2007-12-23 11:41) [16]

Используй ограниченный вариант string - shortstring.


 
savyhinst ©   (2007-12-23 13:01) [17]

Извините, конечно за мою тупость и неподточенность, но я вот понаделал тут, что мне посоветовали. И поначалу приходила пустота, а потом мною было решено: shortstring+stdcall - должно быть железно, как integer или smallint; это же сами данные, а не указатель на них, как string или PChar. И теперь не приходит ничего, и по исполнению процедуры приходит Access violation (read) in <Моя программа>. Что делать?


 
Григорьев Антон ©   (2007-12-23 13:12) [18]


> savyhinst ©   (23.12.07 13:01) [17]

Вы такое выражение - "Ошибка в 17 строке" - слышали? Оно означает, что пока не будет показан код, сказать, где именно ошибка, невозможно. Так вот, у вас ошибка именно в этой строке.


 
Германн ©   (2007-12-23 13:55) [19]


> а потом мною было решено: shortstring+stdcall - должно быть
> железно

Можно подумать что stdcall это волшебное слово. Стоит только его написать как сразу все заработает.
Кстати в том своем обрывочном примере в http://delphimaster.net/view/2-1198342227/ это слово не было упомянуто нигде. Так как прикажешь понимать тебя, Саид?


 
savyhinst ©   (2007-12-23 14:17) [20]

надеясь, что вы мне поможете:
library:
...
procedure SetMyDir(const _myDir:shortstring);
begin
 myDir:=_myDir;
 ShowMessage(myDir);
end;
...
exports
 SetMyDir name "Effdll_setDllDirectory";
...

program:
...
 type TSetDllIniProc=procedure(const ininame:shortstring);
...
var  
 iniDllnameProc:TSetDllIniProc;
 libHandle:THandle;
 str_libname:string;
 shString:string;
begin
 shString:=ini.FileName;
 ShowMessage(shString); //ok
 libHandle:=LoadLibrary(PAnsiChar(str_libname));
 if libHandle=0 then raise exception.Create("Can"t load effects library");  
 @iniDllnameProc:=GetProcAddress(libHandle,cnst_setDllIniProcName);
 if @iniDllNameProc=nil then raise exception.Create("Can"t load prefixProc");
 iniDllnameProc(shString);
end;


 
Германн ©   (2007-12-23 14:39) [21]

Во-первых почему ты мешаешь string c shortstring?
Во-вторых где же все таки прячется тот самый stdcall?


 
irish_34   (2007-12-23 17:39) [22]

извините за вторжение, я наверное всех тут замучила, но можно спросить?
если всё работает но после сеанса работы возникает ошибка инструкция по памяти 0*00000000 обратилась к патяти по адресу 0*00000000, источник её такой же как ошибки AV?


 
Sairex ©   (2007-12-24 15:43) [23]


> DiamondShark ©   (22.12.07 22:00) [15]
>
> > GetMem(P,1024);
> > lstrcpy(p,S);
> > MyProcDll(p);
>
> Вот так и появлятся программы, которые атакуются методом
> переполнения буфера.

Незнаю как у Вас но у меня все работает превосходно... И пока никто еще не жаловался на такую обшибку.


 
Eraser ©   (2007-12-24 16:40) [24]


> Sairex ©   (24.12.07 15:43) [23]


>  lstrcpy(p,S);

сюда можно передать стороку, которая длинее выделенного буффера, если правильно сформатировать эту строку, то можно выполнить произвольный код с правами вашего приложения.


 
Сергей М. ©   (2007-12-25 11:06) [25]


> irish_34   (23.12.07 17:39) [22]


> источник её такой же как ошибки AV?


Это и есть AV.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.01.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.007 c
15-1198229544
boriskb
2007-12-21 12:32
2008.01.27
Опять офтоп


2-1198184627
ProgRAMmer Dimonych
2007-12-21 00:03
2008.01.27
Проконсультируйте по поводу работы с файлами


2-1198508759
Kvendi
2007-12-24 18:05
2008.01.27
Скриншот некого чужого окна


4-1182518359
Dib@zol
2007-06-22 17:19
2008.01.27
И снова шрифты


2-1198427858
Ezorcist
2007-12-23 19:37
2008.01.27
read div real





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский