简体   繁体   English

从C调用PHP函数后,扩展段出现段错误

[英]Seg fault in extension after calling PHP function from C

I am trying to write an extension that calls back a PHP function after doing stuff. 我正在尝试编写一个扩展,可以在完成工作后回调PHP函数。 To check feasibility, I went as per this article: https://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/ 为了检查可行性,我按照这篇文章进行操作: https : //devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/

The basic extension worked fine. 基本扩展正常。 Then I added code to call PHP function like this: 然后,我添加了如下代码来调用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);
}

and the calling PHP: 和调用PHP:

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

echo hello_world();

?>

It does call the PHP function and can see the value, but throws a Seg fault after that: 它确实调用了PHP函数并可以看到该值,但此后引发了Seg错误:

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

I am trying on MacOS 10.12.6 with PHP that came with it (5.6.30). 我正在MacOS 10.12.6上尝试使用附带的PHP(5.6.30)。

Any idea how to overcome the Seg fault? 任何想法如何克服段错误?

You need to allocate the return value zval on the stack. 您需要在堆栈上分配返回值zval The pointer passed into call_user_function must be non-NULL. 传递给call_user_function的指针必须为非NULL。 Here's a patch that should fix the issue. 这是一个应解决此问题的补丁。

--- 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 */

It's perfectly fine to pass in a pointer to stack-allocated memory since the PHP engine will never capture a reference to the return value zval anywhere in the call (since the return value is unnamed in userspace). 传递指向堆栈分配的内存的指针非常好,因为PHP引擎永远不会在调用的任何地方捕获对返回值zval的引用(因为返回值在用户空间中未命名)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM