LINUX.ORG.RU

perlembed & garbage collection или не дайте умереть дураком


0

0

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

Вопрос в сущности простой. 

Делаю я в своей С-программе следующее

---
	HV* hvcmd = newHV();
	SV* keystr = newSVpv("str", 4);
	SV* keybin = newSVpv("bin", 4);

	SV* strs[2];
	SV* bins[2];
	strs[0] = newSVpv("str1", 5);
	strs[1] = newSVpv("str2", 5);
	bins[0] = newSVpv("bin1", 5);
	bins[1] = newSVpv("bin2", 5);
	AV* avstr = av_make(2, (SV**)strs);
	AV* avbin = av_make(2, (SV**)bins);
	
	hv_store(hvcmd, "str", 3, newRV_noinc((SV*)avstr), 0);
	hv_store(hvcmd, "bin", 3, newRV_noinc((SV*)avbin), 0);

	AV* inCmds = get_av("g_inCmd", TRUE);
	av_push(inCmds, newRV_noinc((SV*)hvcmd));
	
	call_argv("q", G_DISCARD | G_NOARGS, NULL);
---
Причем делаю это в цикле...

В функции q я его собственно печатаю и даллее очищаю:
---
sub q
{
	print Data::Dumper->Dump([\@g_inCmd], [qw(g_inCmd)]), " \n";
	@g_inCmd = ();
}
---

В итоге на каждой иттерации получаю массив хешей массивов типа:
$g_inCmd = [
             {
               'bin' => [
                          'bin1',
                          'bin2'
                        ],
               'str' => [
                          'str1',
                          'str2'
                        ]
             },
				...];


Внимание вопрос: объясните дураку почему у меня память течет?
Можно ткнуть в конкретное место perlguts или perlapi...
Ну простите, не понял я еще до конца как он внутри устроен... ;(

игрался я и с 	
strs[0] = sv_2mortal(newSVpv("str1", 5));
и с 
sv_unref(strs[0]);

В общем налицо непонимание... ;-\

Упрощаем вопрос... Как вообще грохнуть эти переменные??

Если я делаю

SV* q = newSViv(28);
...
sv_free(q);
Все обалдеть работает -- никудане течет...

Если я делаю:
SV* q = sv_2mortal(newSViv(28));
то sv_free уже не вызвать ибо "Attempt to free temp prematurely: SV 0xXXX"

И память начинает тесь на ура... В чем смертность q и как ее достичь, а? ;-\

Мне нужна простая штука: создавать структуру данных в С, а освобождать сборщиком мусора 
-- когда я в перле скажу, что @g_inCmd = (); (это уже в терминах предыдущего вопроса)...

Пожалуйста... %-\

tarle
() автор топика
Ответ на: комментарий от tarle

sv_2mortal() помещает sv в tmps_stack, при выходе
из блока (точнее, после FREETMPS) у этой переменной
будет уменьшен счетчик ссылок.

то есть вам не следует класть mortal обьекты в массив.
вместо этого вам нужно обеспечить, чтобы REFCNT у элементов
массива было == 1. тогда после @g_inCmd = () они будут
освобождены. если эти элементы сами являются контейнерами,
то, их элементы должны иметь REFCNT == 1 и так далее
рекурсивно.

> SV* keystr = newSVpv("str", 4);
> SV* keybin = newSVpv("bin", 4);

больше не используются, утечка.

> AV* avstr = av_make(2, (SV**)strs);
> AV* avbin = av_make(2, (SV**)bins);

утекли avstr и avbin. проще всего сделать
sv_free(strs[0]); sv_free(strs[1]);

если вы сделаете им sv_2mortal(), они не будут
освобождаться в цикле, а будут висеть до выхода
из функции как минимум, пока не будет FREETMPS.

вообще, в данном случае av_make() не самый лучший
подход, вы копируете скаляры, вместо того, чтобы
просто добавить два элемента.

idle ★★★★★
()
Ответ на: комментарий от idle

>> SV* keystr = newSVpv("str", 4);
>> SV* keybin = newSVpv("bin", 4);

>больше не используются, утечка.

Простите, а вы не подскажете где пишут про то что используется, а что не 
используется и течет? Или это только на собственных шишках?.. ;)
Правильным тогда здесь будет newSV(), а затем sv_set*()?

>> AV* avstr = av_make(2, (SV**)strs);
>> AV* avbin = av_make(2, (SV**)bins);
>
>вообще, в данном случае av_make() не самый лучший
>подход, вы копируете скаляры, вместо того, чтобы
>просто добавить два элемента.

Имеется ввиду av_push()? Без последующего удаления (SV*)?

Кстати спасибо... ;)

tarle
() автор топика
Ответ на: комментарий от tarle

> > > SV* keystr = newSVpv("str", 4);
> >
> > больше не используются, утечка.
>
> Правильным тогда здесь будет newSV(), а затем sv_set*()?

да это то же самое! вы создаете SV, для него и его
содержимого выделяется память, и потом этот скаляр
нигде не используется и perl про него не знает.

> > > AV* avstr = av_make(2, (SV**)strs);
> > > AV* avbin = av_make(2, (SV**)bins);
> >
> > вообще, в данном случае av_make() не самый лучший
> > подход, вы копируете скаляры, вместо того, чтобы
> > просто добавить два элемента.
>
> Имеется ввиду av_push()? Без последующего удаления (SV*)?

av_make() тот же av_push() в цикле, только кладется _копия_
SV*, а оригинал у вас и утекает. в случае av_push() удалять
SV не надо: обьект теперь принадлежит массиву, и будет удален
самим массивом, когда будет сделано @array = (), вы ведь
этого хотели?

idle ★★★★★
()
Ответ на: комментарий от idle

Все спасибо. Я не совсем кретин, как это могло показаться после моего предыдущего сообщения (которое к вашему ответу было). Просто мы немного разошлись в терминах... ;)

Спасибо огромное.

tarle
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.