powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / подтекает память ( из UDF ? )
25 сообщений из 40, страница 1 из 2
подтекает память ( из UDF ? )
    #39253173
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стоит на линуксе firebird2.5-super-server 2.5.0.26054 - текущая последняя версия из дистрибутива дебиан 7.
Некоторое время назад размер процессов начал расти. Подтекает весьма интенсивно. В сутки 1-1.5 гб. Так что уже приходится перезапускать процесс.

Конфиг firebird.conf почти не трогался даже. Там только насчет UDF изменения.
Про то, что можно для каждой базы поменять настройки памяти никто в этой инсталляции не знает даже. То есть, все дефолтное.
Очевидная причина - самописные UDF.
Как бы определить утекает она из-за особенностей UDF или просто растет потому что так и должно быть ?

В базе всегда были UDF . библиотечка называлась ibu.c и меня уверяют, что все написано по канонам.
Код, вероятно, общеизвестный . Есть выделение памяти :
Код: plaintext
1.
2.
3.
4.
void* ib_util_malloc(long size)
{
        return malloc(size);
}


и такого рода несколько процедур, где этот malloc потом используется:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
char * upcase(const char *s)
{
  if (!s)
    return 0;

  char* buf = (char *) ib_util_malloc(strlen(s) + 1);
  char* p = buf;
  while (*s)
  {

..
  *p = '\0';
  return buf;
}


Однако мне не понятно каким образом эта память должна освобождаться.
FB получает результат, использует, а дальше что ?
Это вообще правильно написано ?

допустим, я нашел примеры написания udf,
там в том же ключе функции написаны. например такое :

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
/*====================================================================
  File Name:	udflib.c
  Description:
  This module contains some user defined functions (UDF).  
  The test suite for UDF will use udf.sql
  to define UDF to the database using SQL statements.
 * The contents of this file are subject to the Interbase Public


....
char* EXPORT fn_lower_c(char* s) /* VARCHAR input */
{
	char *buf;
	short length = 0;

	char *buffer = (char *)malloc(256);

	length = (short)*s;
	s += 2;
	buf = buffer;
	while (*s)
		if (*s >= 'A' && *s <= 'Z')
			*buf++ = *s++ - 'A' + 'a';
		else
			*buf++ = *s++;

	*buf = '\0';
	buffer [length] = '\0';

	return buffer;
}




Но кто обещал что примеры udf правильные ? какие еще могут быть причины ?

Куда теперь копать ?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253177
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindЕсть выделение памяти :
Я очень надеюсь, что эта функция не в той самой библиотеке...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253179
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwind,

дело не только в написании функции, но и в ее объявлении в SQL. У меня на сайте есть пример
http://www.ibase.ru/files/download/safeudf.zip
на pascal, с тремя вариантами объявления функций с возвращаемыми параметрами.

Так вот, если ты хочешь, чтобы функция аллокировала память под результат внутри себя, а ФБ его освобождал, то
- функция должна содержать вызов ib_util_malloc
- функция должна быть объявлена с возвращаемым параметром по FREE_IT.

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

То есть, FREE_IT это как бы "дайте мне функцию, результат которой аллокирован известным мне способом, и я смогу эту память освободить". Поэтому использовать нужно только ib_util_malloc из ib_util, который скомпилирован тем же рантаймом, что и ФБ.
Если использовать просто malloc, то рантаймы могут не совпадать, и память может быть освобождена ФБ некорректно.

Кроме того, А в твоем коде (я не силен в С, могу ошибаться)
Код: plaintext
1.
2.
  if (!s)
    return 0;


никакого аллокирования не происходит. Что будет в результате при попытке ФБ освободить возвращаемый результат, я не знаю (не помню уже).

netwindКод, вероятно, общеизвестный . Есть выделение памяти :
это чушь какая-то. См. выше - ib_util_malloc вызывается из либы ib_util, и в дистрибутиве ФБ есть как эта либа, так и ее заголовок ib_util.h.
netwindКуда теперь копать ?
исправить самодеятельность в ib_util_malloc.
ну напиши процедуру, которая вызывает такую функцию с рандомным (и пустым) результатом, миллионов 5-10 раз, и смотри на потребление памяти ФБ. Если утечка есть, значит дело табак.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253180
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindтам в том же ключе функции написаны. например такое :
В оригинальном udflib.c написано вот так
Код: plaintext
1.
2.
3.
4.
5.
6.
char* EXPORT fn_lower_c(char* s) /* VARCHAR input */
{
	char *buf;
	short length = 0;

	char *buffer = (char *)ib_util_malloc(256);



и ib_util_malloc именно тот, который из ib_util.dll/ib_util.so.
Если даже брать udflib.c от IB4, то там код другой (free_it еще не было). А в ИБ5 уже free_it.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253207
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdv, тесты отлично подтверждают ваше предположение.
Однако, другая версия библиотеки теперь валится.
В логах /usr/sbin/fbguard: /usr/sbin/fbserver terminated abnormally (127)

Что же тут не так ?
Поставил пакет, все чистенько скомпилировалось вот такой последовательностью команд :
gcc -fPIC -c ibu.c -o ibu.o
gcc -shared -oibu.so ibu.o

я код сократил, привел только одну падающую udf. они все падают одинаково.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
#include <stdlib.h>
#include <string.h>
#include <ib_util.h>
#define EXPORT

int version();
char * upcase(const char *);


int version()
{
return 2;
}


char * upcase(const char *s)
{
  if (!s)
    return 0;

  char* buf = (char *) ib_util_malloc(strlen(s) + 1);
  char* p = buf;
  while (*s)
  {
    if (*s >= 'а' && *s <= 'я') {
      *p++ = *s++ - 'а' + 'А';
    }
    else
    if (*s >= 'a' && *s <= 'z') {
      *p++ = *s++ - 'a' + 'A';
    }
    else
    if (*s == 'ё') {
      *p++ = *s++ - 'ё' + 'Ё';
    }
    else
      *p++ = *s++;
  }
  *p = '\0';
  return buf;
}



тут понятно что эта странная функция для windows-1251 работает только.

Декларация в SQL такая
DECLARE EXTERNAL FUNCTION UPCASE2000 CSTRING(2000)
RETURNS CSTRING(2000)
ENTRY_POINT 'upcase' MODULE_NAME 'ibu';

free_it ставили и не ставили - без разницы падает.

Что теперь не так ?

Откуда взялась эта манера передекларировать malloc - не понятно. Библиотека долго мигрировала между версиями. Потери памяти ведь небольшие и годами этого не замечали. Надо думать, неспроста такие декларации были сделаны - пакеты не смогли поставить, например.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253210
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindchar* buf = (char *) ib_util_malloc(strlen(s) + 1);
RETURNS CSTRING(2000)
free-it тут нет, а память под возврат аллокируется в функции, и фактически замещает то, что ожидает получить ФБ.
Вы почитайте safeudf.dpr из файла по ссылке выше. Я там все расписал предельно просто и понятно.

В этой вашей upcase при такой декларации (без free_it) нужно модифицировать входную переменную, и ее же возвращать.
netwindНадо думать, неспроста такие декларации были сделаны - пакеты не смогли поставить, например.
какие еще пакеты?

А насчет того, почему падает - у вас объявление функции кривое, как мне кажется. Например
udflib.c - char* EXPORT fn_lower_c(char* s)
fbudf.c - FBUDF_API void getExactTimestamp(ISC_TIMESTAMP* rc)
где
#define FBUDF_API __declspec(dllexport)

а у вас - просто char * upcase(const char *s)

и все. где явное указание типа вызова?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253212
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindОткуда взялась эта манера передекларировать malloc - не понятно.
откуда вообще взялась манера писать отсебятину в udf. :-) Есть же правила, которые давным-давно написаны. Если правила непонятны, то надо использовать готовые примеры (официальные или однозначно рабочие) как болванки.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253214
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindБиблиотека долго мигрировала между версиями. Потери памяти ведь небольшие и годами этого не замечали.
еще добавлю - такая ситуация как у вас, встречается не впервые. Например, кривой тип вызова (stdcall вместо cdecl) в udf на delphi мог не приводить ни к каким фатальным результатам. А начиная с определенного момента - переезд сервера на другую ОС или на новую версию ФБ, или даже просто на сервер добавили памяти или поставили другой софт - хлоп, и или сервер начинает падать, или функция возвращает мусор из памяти.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253216
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvnetwindchar* buf = (char *) ib_util_malloc(strlen(s) + 1);
RETURNS CSTRING(2000)
free-it тут нет, а память под возврат аллокируется в функции, и фактически замещает то, что ожидает получить ФБ.
Вы почитайте safeudf.dpr из файла по ссылке выше. Я там все расписал предельно просто и понятно.

Да, все понятно. Это я неверное объявление скопировал. Падает не зависимо от наличия free_it.


авторВ этой вашей upcase при такой декларации (без free_it) нужно модифицировать входную переменную, и ее же возвращать.
совсем нет, мне это не нужно.

netwindНадо думать, неспроста такие декларации были сделаны - пакеты не смогли поставить, например.
какие еще пакеты?

Пакеты в линуксе. Люди не могут поставить их, найти все заголовки .h и выдумывают что попало.
Однако, я поискал и обнаружил старую версию в ветке 2.5 . Там тот самый malloc ! Это не фантазия разработчика, а официальный пример для 2.5
https://github.com/FirebirdSQL/firebird/blob/B2_5_Release/examples/udf/udflib.c
А в ветке 3.0 уже поновее код. От него попытаюсь отталкиваться.


авторА насчет того, почему падает - у вас объявление функции кривое, как мне кажется. Например
udflib.c - char* EXPORT fn_lower_c(char* s)
fbudf.c - FBUDF_API void getExactTimestamp(ISC_TIMESTAMP* rc)
где
#define FBUDF_API __declspec(dllexport)

а у вас - просто char * upcase(const char *s)

и все. где явное указание типа вызова?
Пробовал и EXPORT определять. Но ведь он пустой
теперь у меня следующий код по мотивам
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ibase.h>
#include "example.h"
#include <ib_util.h>

char *  upcase(const char *);

char* EXPORT upcase(const char *s)



EXPORT из example.h весьма банален ( https://raw.githubusercontent.com/FirebirdSQL/firebird/B3_0_Release/examples/include/example.h)
Код: plaintext
1.
2.
3.
4.
5.
#if defined __BORLANDC__ && defined __WIN32__
#define EXPORT _export
#else
#define EXPORT
#endif


То есть, объявление типа бессмысленно

продолжает падать.

Какие современные примеры на C лучше посмотреть ?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253218
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindОднако, я поискал и обнаружил старую версию в ветке 2.5 . Там тот самый malloc ! Это не фантазия разработчика, а официальный пример для 2.5
кстати, да, подтверждаю, у меня в дистре 2.5 тот же ужас в udflib.c. Это кто-то проехался search/replace.
netwindТо есть, объявление типа бессмысленно
тогда не знаю.
Вот другой пример, из ib_util.h
Код: plaintext
1.
2.
3.
4.
5.
#ifdef __cplusplus
extern "C" {
#endif

extern void *ib_util_malloc(long);


netwindКакие современные примеры на C лучше посмотреть ?
fbudf, rfunc.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253219
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindЧто же тут не так ?
Поставил пакет, все чистенько скомпилировалось вот такой последовательностью команд :
gcc -fPIC -c ibu.c -o ibu.o
gcc -shared -oibu.so ibu.oГде линковка с ib_util ?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39253225
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad, вот это отличное замечание.
Компилить мне надо так :
gcc -c -O -fpic ibu.c
ld -G ibu.o -lm -lc -lib_util -o ibu.so

Все заработало, память не течет !

Почему же диагностика firebird не могла эту ситуацию распознать и выдать какие-нибудь наводящие ошибки ?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267032
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все переписали, но память продолжает течь хотя и с меньшей в 3 раза скоростью.
сделал с помощью gdb core dump по-живому и пытаюсь смотреть на память как файл - буфер напоминает набор 32битных указателей. Ну типа стек или что-то связанное. А прошлый раз тем же способом я увидел характерные строки.

Один раз я все-таки увидел на графике самопроизвольное уменьшение памяти, но это нечасто происходит.

Что же еще не так и что еще проверить ? Приложение (не смейтесь) на дельфи.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267042
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindПриложение (не смейтесь) на дельфи.

Значит все утечки памяти способен обнаружить FastMM.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267047
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov, судя по описанию, это для клиентской стороны особый менеджер памяти. но как он обнаружит утечки на сервере firebird ?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267049
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну да, сам он их не обнаружит. Для этого к нему нужен ещё и программист.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267051
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov, или вы меня вообще не понимаете или эта чудо-программа умудряется проверять всевозможные забытые в клиентском приложение дескрипторы FB, подтверждение чего я не нахожу.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267053
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindэта чудо-программа умудряется проверять всевозможные забытые в клиентском приложение
дескрипторы FB

Большинство "забытых в клиентском приложении дескрипторов" светится в соответствующих
таблицах мониторинга. Но тут уже нужен DBA.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267070
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov, уже лучше. Вызываю вертолет с DBA :)
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267108
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindПриложение (не смейтесь) на дельфи.
Приложение или udf на дельфи?
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267110
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindDimitry Sibiryakov, судя по описанию, это для клиентской стороны особый менеджер памяти. но как он обнаружит утечки на сервере firebird ?Этот shared менеджер памяти не обнаруживает никаких утечек. Если функция объявлена с FREE_IT, для сервера Firebird это "сигнал", что буфер под результат был выделен через ib_util_malloc и что его необходимо очистить соответствующим образом. Всё! Если в udf'ке, для каких-либо иных нужд, необходимо выделить буфер, этот буфер должен выделяться обычным си-библиотечным std::malloc (ib_util_malloc ИСКЛЮЧИТЕЛЬНО для возврата серверу результата из udf).
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267176
netwind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman, udf на классическом C и тексты функций я даже приводил некоторые.

Сейчас в тексте udf нет левых malloc, так что я не представляю как еще можно создать утечку. Есть другие способы ?

Видимо, теперь мне надо сосредоточиться на изучении служебных таблиц чтобы понять что еще не освобождает приложение.
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267185
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindСейчас в тексте udf нет левых malloc, так что я не представляю как еще можно создать
утечку. Есть другие способы ?

Утечку можно создать и правыми malloc().
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267199
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindСейчас в тексте udf нет левых malloc, так что я не представляю как еще можно создать утечку. Есть другие способы ?Забыть написать FREE_IT в декларации UDF
...
Рейтинг: 0 / 0
подтекает память ( из UDF ? )
    #39267269
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netwindСейчас в тексте udf нет левых malloc, так что я не представляю как еще можно создать утечку. Есть другие способы ?

Видимо, теперь мне надо сосредоточиться на изучении служебных таблиц чтобы понять что еще не освобождает приложение.Полно! Есть, к примеру, "способ" выделить через std::malloc память, проинициализировать её адресом указатель - член класса в экземпляре класса и забыть прописать в деструкторе освобождение этой памяти через std::free.
...
Рейтинг: 0 / 0
25 сообщений из 40, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / подтекает память ( из UDF ? )
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]