2015-01-21 89 views
0

在PHP扩展,也正是这一区别:和PHP扩展 - RETURN_STRING

PHP_METHOD(TestExtension, test) 
{ 
    MyClass *myclass; 
    MyClass_Object *obj = (MyClass_Object*)zend_object_store_get_object(getThis() TSRMLS_CC); 
    myclass = obj->myclass; 
    if (myclass != NULL) 
    { 
    string retval = myclass->test(); 
    RETURN_STRING(retval.c_str(), 1); 
    } 
    RETURN_NULL(); 
} 

这样的:

PHP_METHOD(TestExtension, test) 
{ 
    MyClass *myclass; 
    MyClass_Object *obj = (MyClass_Object*)zend_object_store_get_object(getThis() TSRMLS_CC); 
    myclass = obj->myclass; 
    if (myclass != NULL) 
    { 
    RETURN_STRING(myclass->test().c_str(), 1); 
    } 
    RETURN_NULL(); 
} 

两个似乎工作,但是当我的valgrind运行:

valgrind --tool=memcheck --num-callers=30 --log-file=./php.log /usr/bin/php test.php 

其中test.php的是:

<?php 
    $obj = new TestExtension("testing"); 
    echo $obj->test() . "\n"; 
?> 

那么后者给了我一大堆的错误,所有其中有:

Address 0xe4c3e98 is 24 bytes inside a block of size 66 free'd 

valgrind摘要如下:

126 ==23067== HEAP SUMMARY: 
127 ==23067==  in use at exit: 9,031 bytes in 15 blocks 
128 ==23067== total heap usage: 25,131 allocs, 25,116 frees, 4,435,757 bytes allocated 
129 ==23067== 
130 ==23067== LEAK SUMMARY: 
131 ==23067== definitely lost: 0 bytes in 0 blocks 
132 ==23067== indirectly lost: 0 bytes in 0 blocks 
133 ==23067==  possibly lost: 0 bytes in 0 blocks 
134 ==23067== still reachable: 9,031 bytes in 15 blocks 
135 ==23067==   suppressed: 0 bytes in 0 blocks 
136 ==23067== Rerun with --leak-check=full to see details of leaked memory 
137 ==23067== 
138 ==23067== For counts of detected and suppressed errors, rerun with: -v 
139 ==23067== ERROR SUMMARY: 48 errors from 5 contexts (suppressed: 0 from 0) 
+0

在RETURN_STRING()中myClass-> test()之后缺少逗号? – damndaewoo 2015-01-21 11:03:34

+1

没有缺失的逗号。 – 2015-01-21 11:16:29

回答

1

虽然它不是为RETURN_STRING宏文档中所述(这似乎是一个疏漏:它绝对应该态寿命的要求),它会出现在宏扩展到多行。

说,例如:

RETURN_STRING(myclass->test().c_str(), 1); 

变为:

const char* arg = myclass->test().c_str(); 
someCode(); 
someMoreCode(); 
finalCode(arg); 

arg无效的最后一行,因为(假定它返回由值)的myclass->test()临时结果仅存在用于第一行的持续时间。因此myclass->test().c_str()的结果也仅在第一行的有效期内有效。 arg立即成为悬挂指针。

您的解决方法是解决此问题的正确方法。我会建议,在使用任何这些宏时,确保您通过一个指向的指针,确保至少在宏运行时仍然存在,无论涉及多少个语句/表达式。

这里就是我想要做的:

if (myclass != NULL) { 
    const string& retval = myclass->test(); 
    RETURN_STRING(retval.c_str(), 1); 
} 

现在,不管什么myclass->test(),它会生存下去的所有宏的扩展的语句,你没有将它复制到一个新的std::string目的。

+0

谢谢!我应该看看这个宏。我还在摸索PHP扩展的方式。出于兴趣,你使用什么文档? – 2015-01-21 13:50:52

+0

@VanessaDeagan:我不写PHP扩展。所以,没有。 :) – 2015-01-21 16:25:53

+0

我写了一些PHP扩展,我会建议github和stackoverflow搜索示例代码,有一些有组织的文档,其中一些是在phpinternals书和其他一些部分是在PHP黑客手册,但是,是的,你'要找到很难找到文件:( – 2016-06-19 09:46:46