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

Вниз

Установил Yaffil_877ss. Не работает UDF.   Найти похожие ветки 

 
kaif   (2004-01-15 17:45) [0]

Работал на Yaffil_821ss. Установил Yaffil_877ss.
Перестала вызываться моя функция из UDF.
Ошибка "function FROMAT_DATETIME could not be matched"
При этом "стандартные функции IB" работают.
---------------------
DECLARE EXTERNAL FUNCTION FORMAT_DATETIME
CSTRING(30) CHARACTER SET WIN1251, TIMESTAMP
RETURNS CSTRING(30) CHARACTER SET WIN1251 FREE_IT
ENTRY_POINT "FmtIBDateTime" MODULE_NAME "alg_udf";
эта функция не работает (она моя)
---------------------
DECLARE EXTERNAL FUNCTION strlen
CSTRING(32767)
RETURNS INTEGER BY VALUE
ENTRY_POINT "IB_UDF_strlen" MODULE_NAME "ib_udf";
эта функция работает (она стандартная)
-----------------------
Судя по тексту ошибки, функция не находится по имени.
----------------------------
То, что я нашел в FAQ я не очень понимаю:

Yaffil начиная со сборки 867 компилируется MSVC7. Это означает, что теперь используется сервисная библиотека msvcr7.dll, а не msvcrt.dll как раньше (msvc6). В этой библиотеке есть функция malloc, отвечающая за аллокирование памяти.

Таким образом, если ваши udf содержат фунции с free_it, которые напрямую аллокируют память вызовом функции из msvcrt, или наоборот, делают это правильно через ib_util.dll но от сервера IB или FB, в результате получается что ваша udf использует один менеджер памяти, а сервер - другой. Что и приводит ко всяким проблемам с работоспособностью сервера.

Убедитесь, что ваша функция использует вызов не malloc, а ib_util_malloc, и что ib_util.dll имеет версию Yaffil не ниже 865 сборки (а также что на компьютере нет других ib_util.dll, которые могут быть найдены операционной системой ранее правильной ib_util.dll).


Я как-то работал с MSVC7 и мне кажется, что там имена в dll как-то странно приходилось давать (со знаком подчеркивания или как - не помню). К тому же я понимаю, что мне нужно что-то менять в аллокировании памяти (но это уже видимо другая ошибка, которая пока не проявляется, так как не работает сама функция). Подозреваю, что я вообще должен поменять аллокирование памяти, но как правильно - не знаю. Мой текст функции привожу:

function FmtIBDateTime(FmtStr: PChar; var Value: TISC_QUAD): PChar; cdecl; // free_it
var
Tmp: String;
begin
try
Tmp:= FormatDateTime(StrPas(FmtStr), QuadToDate(Value));
GetMem(Result, Length(Tmp)+1);
try
StrCopy(Result, PChar(Tmp));
except
FreeMem(Result);
raise;
end;
except
Result:= nil;
end;
end;


------------
Буду благодарен за любые разъяснения и любую помощь в правильном написании этой функции.


 
Vlad   (2004-01-15 18:27) [1]

Проблемы не в реализации функции- однозначно.
Скорее либо библиотеку найти не может, либо Entry Point
Попробуй почитать тут:
http://community.borland.com/article/0,1410,25445,00.html
и тут:
http://www.ibase.ru/v6/ib6faq.htm#udf


 
jack128   (2004-01-15 18:35) [2]


> Убедитесь, что ваша функция использует вызов не malloc,
> а ib_util_malloc, и что ib_util.dll имеет версию Yaffil
> не ниже 865 сборки (а также что на компьютере нет других
> ib_util.dll, которые могут быть найдены операционной системой
> ранее правильной ib_util.dll).


> GetMem(Result, Length(Tmp)+1);

Как это понимать? ;-)


 
Desdechado   (2004-01-15 18:37) [3]

опечатка или нет, но в тексте ошибки FROMAT, а в описании FORMAT


 
Vlad   (2004-01-15 18:38) [4]


> jack128 © (15.01.04 18:35) [2]

А чего тут понимать ? Выделение пямяти под Result, проблема явно не в этом.


 
Desdechado   (2004-01-15 18:40) [5]

> Yaffil начиная со сборки 867 компилируется MSVC7
вот это мне не нравится. А общий проект Firebird-Yaffil после объединения на чем лепить будут?


 
jack128   (2004-01-15 18:44) [6]


> А чего тут понимать ? Выделение пямяти под Result, проблема
> явно не в этом.
внимательно считываемся в цитату кайфа, насчет того какой функцией должна выделяться память под free_it результат.


 
Vlad   (2004-01-15 18:47) [7]


> jack128 © (15.01.04 18:44) [6]

Максимум что может быть, так это ошибка Invalid Pointer Operation при выполнении этой ф-ции, хотя лично я в Yaffil"овских UDF все время GetMem пользовался, проблем еще ни разу не было.


 
jack128   (2004-01-15 19:06) [8]


> Vlad © (15.01.04 18:47) [7]


> UDF все время GetMem пользовался, проблем еще ни разу не
> было.
То что проблем нету сейчас не означает. что их небудет потом(например в новой версии Delphi). Меня вообще то больше интересует зачем kaif привел эту цитату, если сам не соблюдается данные в ней рекомендации ;-)


 
Vlad   (2004-01-15 19:10) [9]


> jack128 © (15.01.04 19:06) [8]


> То что проблем нету сейчас не означает. что их небудет
> потом(например в новой версии Delphi)

Скорее в новой версии Yaffil.
На самом деле ошибка совершенно не связана с реализацией функции. Судя по тексту ошибки, и первой моей ссылке из [1], до выполнения функции дело вобще не доходит.


 
jack128   (2004-01-15 19:20) [10]


> Судя по тексту ошибки, функция не находится по имени.
как функция экспортируется? Имена функций в dll - регистрочувствительны.


 
kaif   (2004-01-15 19:28) [11]

Дико извиняюсь!!!
Действительно, при деинсталляции прежнего Yaffil у меня удалилась моя dll из каталога UDF. Так как тот инсталлятор я сам писал и заодно включил свою dll в инсталляцию. :(
Так что UDF заработали. Но что касается новой mvcrt это меня озадачило.

2 Desdechado © (15.01.04 18:37) [3]
Ошибка "function FORMAT_DATETIME could not be matched". Я опечатался, набирая текст от руки.

2 jack128 © (15.01.04 19:06) [8]
Я этот FAQ прочитал только сегодня. Я и не знал, что нельзя использовать дельфийский менеджер памяти GetMem. Скорее всего, я с самого начала делал что-то неправильно. Но так как это работало, а утечки ресурсов я не наблюдал, я думал, что действую верно... Видимо, жестоко ошибался.

2 Vlad
Большое спасибо за ссылку!!!!!!!!!!!!

Как правильно аллокировать память для UDF с FREE_IT?

Нужно делать следующим образом - начиная с InterBase 5.0 в комплект сервера входит ib_util.dll содержащая функцию ib_util_malloc. Ее объявления для C и Pascal есть в каталоге include:

ib_util.h - extern void * ib_util_malloc (long);
ib_util.pas - function ib_util_malloc(l: integer): pointer; cdecl; external "ib_util.dll";

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

При этом ib_util.dll должна находиться в PATH или рядом с вашей dll UDF. Позаботьтесь о том, чтобы на сервере не было двух или более ib_util.dll от разных серверов. В противном случае возможна некорректная работа сервера, его падение или что еще хуже - повреждение базы данных.

Использование ib_util является 100% переносимым, т.к. эта библиотека является стандартной для Interbase (всех версий выше 5.0), Firebird и Yaffil и поставляется под все платформы.

Если вы сами аллокируете/деаллокируете память внутри UDF (с FREE_IT или без), то можете для этих целей использовать любые функции, в том числе getmem/freemem в Delphi.


Однако последний абзац меня опять озадачил.
Может, кто-то прояснит? Теперь можно использовать GetMem так как я использую, то есть с последующим FREE_IT ?
Я так понимаю, что по логике нельзя... Тогда о чем речь в последнем абзаце?


 
Vlad   (2004-01-15 19:43) [12]


> Я так понимаю, что по логике нельзя... Тогда о чем речь
> в последнем абзаце?

Да фигня всё это. С чего ты взял что GetMem нельзя использовать ?
То что ты прочитал в FAQ означает то, что нельзя использовать ф-цию malloc (вместо нее ib_util_malloc). А GetMem никто не отменял :-)


 
jack128   (2004-01-15 19:45) [13]


> Теперь можно использовать GetMem так как я использую, то
> есть с последующим FREE_IT ?
> Я так понимаю, что по логике нельзя...
Правильно понимаешь.


> Тогда о чем речь в последнем абзаце?
Речь об этом

> function FmtIBDateTime(FmtStr: PChar; var Value: TISC_QUAD):
> PChar; cdecl; // free_it
> var
> Tmp: String;
> begin
> try
> Tmp:= FormatDateTime(StrPas(FmtStr), QuadToDate(Value)); // память под temp аллокирует дельфийский менеджер памяти
> GetMem(Result, Length(Tmp)+1);
> try
> StrCopy(Result, PChar(Tmp));
> except
> FreeMem(Result);
> raise;
> end;
> except
> Result:= nil;
> end;
> end; // Тут он осводождает память из под Temp.
В этом нет ничего странного так как память выделяется/освобождается ПАРНЫМИ функциями.(одним и тем же менаджером памяти)

Поэтому же для free_it результатов память нужно выделять ОБЯЗАТЕЛЬНО c помощью ib_util_malloc, так как сервер осводождает память в помоью парной её функции. То есть выделение/освобождение памяти происходит с помощью одного менаджера памяти.


 
Vlad   (2004-01-15 19:53) [14]


> jack128 © (15.01.04 19:45) [13]

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


 
jack128   (2004-01-15 19:59) [15]


> Если память выделяет один менеджер, а освобождает другой,
> это совершенно не значит что возникнет ошибка
не так мыслишь.
Если память выделяет один менеджер, а освобождает другой, это не значит, что ошибка НЕ возникнет ;-). А так как во внутрености менаджеров мы залесть не можем(или можем, но ВЛО-О-ОМ :-))), то лудше не рисковать.


 
Vlad   (2004-01-15 20:04) [16]


> jack128 © (15.01.04 19:59) [15]

Кстати твои комментарии:

// память под temp аллокирует дельфийский менеджер
// Тут он осводождает память из под Temp.


не совсем верны. Точнее сказать они будут верны если ты сам, собственноручно подключешь в uses менеджер ShareMem.
Без этого, память не будет сама ни выделяться ни освобождаться. А выделяет автор ее ручками (GetMem), освобождает сервер (как показывает практика - успешно). Так что все справедливо.


 
jack128   (2004-01-15 20:09) [17]


> Vlad © (15.01.04 20:04) [16]
Вообще не понял. Кто ж тогда память выделяет? (под temp)


 
Vlad   (2004-01-15 20:15) [18]


> jack128 © (15.01.04 20:09) [17]

Да, сорри, temp - это string, поэтому Delphi сам выделяет и освобождает память.
Но Temp в данном случае не причем, не она же на сервер передается. Речь идет о переменной Result, а под нее автор ручками выделяет память.


 
jack128   (2004-01-15 20:19) [19]

Ну да. Я привел этот пример, что бы показать, что выделять память под переменную, которая НЕ будет передаваться на сервер можно любым менеджером..


 
kaif   (2004-01-15 20:21) [20]

2 jack128 © (15.01.04 19:45) [13]
я правильно тебя понял, что на всякий пожарный мне нужно переписать функцию и вместо GetMem использовать ib_util_malloc ?
Но если это так, то что мне использовать вместо FreeMem?
Или мне вообще выкинуть конструкцию с try .. except ?
А если у меня будут какие-то рискованные вещи и нужно будет использовать try .. except, что мне применять в качестве FreeMem ?
У меня такое ощущение, что народ что-то умалчивает. Или есть еще функция free_it в этой dll и надо именно ее юзать?


 
Vlad   (2004-01-15 20:21) [21]

Да, судя по всему ты прав, последний абзац именно это и означает.

Если вы сами аллокируете......
имелось ввиду, что под любые другие переменные (не Result)


 
Vlad   (2004-01-15 20:23) [22]


> что мне использовать вместо FreeMem?

Вместо Free_Mem сервер будет делать FREE_IT сам, если указана данная опция в UDF


 
Vlad   (2004-01-15 20:46) [23]

Кстати, для полной ясности решил провести небольшой тест.
Использовал UDF, где аллокировал память под Result с помощью GetMem
На небольших таблицах работает четко, но как только пробую делать апдейт с помощью этой функции на таблице с 4 млн записей, то примерно на втором миллионе выдает ошибку....
Так что вот... jack128 © был прав. Выделять память лучше тем же менеджером, который потом будет освобождать.


 
kaif   (2004-01-15 22:24) [24]

2 Vlad © (15.01.04 20:46) [23]
OK. Спасибо большое. Особеннно за эксперимент с GetMem.
Всем спасибо. Век живи - век учись. Пойду исправлять.


 
kaif   (2004-01-15 23:45) [25]

В общем, теперь это выглядит так:

function ib_util_malloc(l: integer): pointer; cdecl; external "ib_util.dll";

function FmtIBDateTime(FmtStr: PChar; var Value: TISC_QUAD): PChar; cdecl; // free_it
var
Tmp: String;
begin
Tmp:= FormatDateTime(StrPas(FmtStr), QuadToDate(Value));
Result := ib_util_malloc(Length(Tmp)+1);
StrCopy(Result, PChar(Tmp));
end;

А в декларации функции, соответственно, FREE_IT

И все в таком духе. Работает. Надеюсь, теперь правильно.
Еще раз спасибо всем.



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

Форум: "Базы";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.023 c
7-16769
Prof
2003-11-18 09:37
2004.02.06
Соединение по модему.


1-16298
Grinder
2004-01-24 13:43
2004.02.06
Форма как hint


11-16204
freeloader
2003-05-22 16:59
2004.02.06
StretchDraw()


8-16522
o2
2003-10-02 14:45
2004.02.06
DirectX


1-16325
NailMan
2004-01-28 13:11
2004.02.06
Потоки: запутался с обработчиком событий





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский