2015-01-21 74 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