2017-02-25 34 views
4

当调用从Perl的C函数,例如使用Inline::C我应该在不会被返回到堆栈上的SV的SV上调用SvREFCNT_dec()吗?

use feature qw(say); 
use strict; 
use warnings; 
use Inline C => './test.c'; 

say "Calling test().."; 
test(); 
say "Finished."; 

其中test.c是:

void test() 
{ 
    SV *sv_variable = newSVpv("test", 0); 

    // do something.. 

    //SvREFCNT_dec(sv_variable); // free variable 
    printf("Returning from test()..\n"); 
    return; 

} 

脚本似乎好工作我是否打电话SvREFCNT_dec(sv_variable)与否。根据perlguts

要释放您创建的SV,请调用SvREFCNT_dec(SV *)。通常 这个调用不是必需的

+2

'newSVpv'与1.您的REFCNT开始可以将其视为'test()'获得引用的所有权。作为引用的所有者,'test()'必须在退出之前减少var的REFCNT或转移var的所有权。所以是的,''svREFCNT_dec'应该由'test()'调用。 – ikegami

回答

4

是的,你应该减少refcount。 (如果你没有,没有立即的坏影响,但你已经造成了内存泄漏。)

perlguts可能说这通常不是必须的,因为大多数SV不仅仅是在C函数内部使用;它们是从Perl空间可访问的结构的一部分或放在堆栈上。

但是请注意,您的代码结构不是例外安全的:如果// do something引发的任何函数将会泄漏sv_variable(因为SvREFCNT_dec永远不会到达)。这可以通过固定做:

SV *sv_variable = sv_2mortal(newSVpv("test", 0)); 

sv_2mortal就像是一个递延SvREFCNT_dec:它会递减引用计数“后”一段时间。

(如果您正在从一个字符串的SV,newSVpvs("test")newSVpv更好,因为它没有计算在运行时的长度)。

+1

所以当使用'sv_2mortal()'时,变量是否返回到堆栈并不重要,它会工作吗?当'test()'返回时(但是在我的例子中的'say“Finished。''语句之前),Perl将释放变量?由于'perlguts'说*“一个xV是致命的,所以它的引用计数被标记为递减,但实际上不会递减,直到”短时间后“。通常,术语”短时间后“意味着一个单独的Perl语句”* –

+2

Re * *因此,当使用sv_2mortal()时,变量是否返回堆栈并不重要,它会工作吗?“是的。 /// Re“*当test()返回*时,Perl将释放该变量,如果使用'SvREFCNT_dec',它将立即释放(假设不存在其他引用)。如果您使用'sv_2mortal',它将在调用者有机会复制它之后被释放(如果它已被返回)。 /// Re“*,但是在我的例子*”中完成“声明之前,”是的。 – ikegami

+2

“*但请注意,您的代码结构不是异常安全*”,C没有例外,所以这不是一个真正的问题。有'longjmps',但是如果你使用这些,你可以使用相当于'try' /'catch'来清理你自己。没有理由使用'sv_2mortal'。 – ikegami

相关问题