0

次のような XSUB があります。

char *
string4()
CODE:
    char *str = strdup("Hello World4");
    int len = strlen(str) + 1;
    New(0, RETVAL, len, char);
    Copy(str, RETVAL, len, char);
    free(str);
OUTPUT:
    RETVAL

しかし、これは valgrind の New() でメモリ リークとして表示され、ループで実行すると、常駐メモリが増加し続けます。

これも使用すると、同じことが得られます。

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;

c ファイルは、未使用の 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 を使用して文字列を返し、メモリを解放する方法はありますか? 助けていただければ幸いです。

4

1 に答える 1

1

他の問題[1]の中で、最初のスニペットは を使用してメモリを割り当てますNewが、割り当てを解除することはありません。

他の問題の中でも、2 番目のスニペットは を使用してメモリを割り当てますstrdupが、割り当てを解除することはありません。

3 番目のスニペットの根本的な問題は、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。を使用するべきではありませんNewNew何年も前に廃止されましたNewxNew私が覚えている限り、ドキュメントにも載っていません。
于 2015-07-31T19:20:55.653 に答える