2015-07-31 3 views
0

У меня есть XSub вроде этого:Perl XS Handling Память Струны

Но это показывает, как утечка памяти, на New(), в Valgrind, и если я запускаю его в петлю резидента память будет продолжать расти.

я получаю то же самое, если я использую этот тоже:

char * 
string2() 
CODE: 
    char *str = strdup("Hello World2"); 
    RETVAL = str; 
OUTPUT: 
    RETVAL 

Я в состоянии предотвратить утечку и увеличение объема памяти, выполнив:

char * 
string3() 
PPCODE: 
    char *str = strdup("Hello World3"); 
    XPUSHs(sv_2mortal(newSVpv(str, 0))); 
    free(str); 

, но проблема с это решение заключается в том, что при компиляции с -Werror я получаю следующие предупреждения/ошибки.

test.c: In function ‘XS_test_string3’: 
/usr/lib/x86_64-linux-gnu/perl/5.20/CORE/XSUB.h:175:28: error: unused variable ‘targ’ [-Werror=unused-variable] 
#define dXSTARG SV * const targ = ((PL_op->op_private & OPpENTERSUB_HASTARG) \ 
          ^
test.c:270:2: note: in expansion of macro ‘dXSTARG’ 
    dXSTARG; 
^
test.c:269:9: error: unused variable ‘RETVAL’ [-Werror=unused-variable] 
    char * RETVAL; 

С файл будет построен с неиспользованной RETVAL:

XS_EUPXS(XS_test_string3); /* prototype to pass -Wmissing-prototypes */ 
XS_EUPXS(XS_test_string3) 
{ 
    dVAR; dXSARGS; 
    if (items != 0) 
     croak_xs_usage(cv, ""); 
    PERL_UNUSED_VAR(ax); /* -Wall */ 
    SP -= items; 
    { 
    char * RETVAL; 
    dXSTARG; 
#line 61 "test.xs" 
    char *str = strdup("Hello World3"); 
    XPUSHs(sv_2mortal(newSVpv(str, 0))); 
    free(str); 
#line 276 "test.c" 
    PUTBACK; 
    return; 
    } 
} 

Так есть лучший способ справиться с возвращением выделенных строк в XS? Есть ли способ вернуть строку с помощью RETVAL и освободить память? Я ценю любую помощь.

ответ

1

Среди прочих проблем [1], ваш первый фрагмент выделяет память с использованием New, но никогда не освобождает его.

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

Основная проблема с вашим третьим фрагментом заключается в том, что вы утверждаете, что функция XS возвращает значение, а это не так. Это значение было бы присвоено RETVAL, которое автоматически создается для этой цели. Переменная не будет создана, если вы правильно укажете, что ничего не возвращаете.

void 
string3() 
PREINIT: 
    char *str; 
PPCODE: 
    str = strdup("Hello World3"); 
    XPUSHs(sv_2mortal(newSVpv(str, 0))); 
    free(str); 

или просто

void 
string3() 
PPCODE: 
    XPUSHs(sv_2mortal(newSVpv("Hello World3", 0))); 

Обратите внимание, что я переехал ваши объявления из PPCODE. В C объявления не могут появляться после не-деклараций, а код в PPCODE может появиться после не деклараций (в зависимости от параметров, используемых для создания Perl). Объявления принадлежат PREINIT. Вы также можете использовать завитки вокруг кода в PPCODE.


  1. Одним из них является использование New. Вы не используете New. New устарел в пользу Newx лет назад. New даже не был в документации до тех пор, как я помню.
+0

Спасибо, что сработало. В секундах, что было бы правильным способом освобождения памяти? – gaijin

+2

@gaijin Во втором примере вы можете освободить память только в пользовательской записи [typemap] (http://perldoc.perl.org/perlxstypemap.html). – nwellnhof

Смежные вопросы