从C呼叫PHP函数后,SEG故障在C中



我正在尝试编写一个扩展程序,该扩展程序在做事后回电。要检查可行性,我按照本文进行了:https://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/

基本扩展工作正常。然后,我添加了代码来调用PHP函数:

PHP_FUNCTION(hello_world)
{
    zval p1;
    INIT_ZVAL(p1);
    ZVAL_STRING(&p1, "From extension", 1);
    zval *params = { &p1 };
    zend_uint param_count = 1;
    zval *retval_ptr = NULL;
    zval function_name;
    INIT_ZVAL(function_name);
    ZVAL_STRING(&function_name, "from_ext", 1);
    if (call_user_function(
            CG(function_table), NULL /* no object */, &function_name,
            retval_ptr, param_count, &params TSRMLS_CC
        ) == SUCCESS
    ) {
        printf("Success returning from PHP");
        if (retval_ptr)
          zval_ptr_dtor(&retval_ptr);
    }
    /* don't forget to free the zvals */
    zval_dtor(&function_name);
    zval_dtor(&p1);
    RETURN_STRING("Hello World", 1);
}

和调用php:

<?
function from_ext($arg) {
  echo "In PHP:", $arg;
  return "hello";
}
echo hello_world();
?>

它确实调用了php函数并可以看到该值,但是在此之后抛出了一个seg故障:

php -dextension=modules/hello.so test.php
In PHP:From extensionSegmentation fault: 11

我正在尝试使用随附的PHP进行MacOS 10.12.6(5.6.30)。

任何想法如何克服SEG故障?

您需要在堆栈上分配返回值zval。转入call_user_function的指针必须是非零的。这是一个应该解决问题的补丁。

--- a/mnt/tmpdisk/a.c
+++ b/mnt/tmpdisk/b.c
@@ -5,7 +5,7 @@ PHP_FUNCTION(hello_world)
     ZVAL_STRING(&p1, "From extension", 1);
     zval *params = { &p1 };
     zend_uint param_count = 1;
-    zval *retval_ptr = NULL;
+    zval retval;
     zval function_name;
     INIT_ZVAL(function_name);
@@ -13,12 +13,11 @@ PHP_FUNCTION(hello_world)
     if (call_user_function(
             CG(function_table), NULL /* no object */, &function_name,
-            retval_ptr, param_count, &params TSRMLS_CC
+            &retval, param_count, &params TSRMLS_CC
         ) == SUCCESS
     ) {
         printf("Success returning from PHP");
-        if (retval_ptr)
-          zval_ptr_dtor(&retval_ptr);
+        zval_dtor(&retval);
     }
     /* don't forget to free the zvals */

将指针输入堆栈分配的内存是完全可以的,因为PHP引擎永远不会捕获对呼叫中任何地方的返回值zval的引用(因为在用户空间中未命名返回值)。

<</p> <</p>

相关内容

  • 没有找到相关文章

最新更新