Segfault在C中自定义PHP扩展中实例化类

时间:2010-10-12 09:15:41

标签: php c segmentation-fault

我正在开发自己的PHP扩展,其中包含一个类。我最近从Ubuntu 9.04升级到9.10并且扩展了。我从尝试更新到10.04,看看它是否修复它,因为我的开发环境是10.04,它在那里工作正常。与我能理解的唯一主要区别是服务器是64位,我的笔记本电脑是32位架构。我有PHP版本5.3.2-1ubuntu4.5(Zend build 20090626)。

我试过运行我的测试PHP文件:

<?php
$server =  "http://localhost/";
$port = 1214;
$f = new PPKeyClient($server, $port);
var_dump($f);

在GDB中:

root@node:/etc/php5/conf.d# gdb php
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /usr/bin/php...Reading symbols from /usr/lib/debug/usr/bin/php5...done.
done.
(gdb) run -f /var/www/test.php 
Starting program: /usr/bin/php -f /var/www/test.php
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffef15b710 (LWP 9228)]
[Thread 0x7fffef15b710 (LWP 9228) exited]
1
Program received signal SIGSEGV, Segmentation fault.
0x00000000006e7767 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fff00000000)
    at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:371
371 /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h: No such file or directory.
 in /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h
(gdb) bt
#0  0x00000000006e7767 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fff00000000)
    at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:371
#1  0x00000000006bec20 in execute (op_array=0xfef1b0) at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:104
#2  0x000000000069694d in zend_execute_scripts (type=0, retval=0x7fffffffbf90, file_count=3)
    at /build/buildd/php5-5.3.2/Zend/zend.c:1266
#3  0x0000000000642598 in php_execute_script (primary_file=0x2) at /build/buildd/php5-5.3.2/main/main.c:2288
#4  0x0000000000727a56 in main (argc=0, argv=0x1) at /build/buildd/php5-5.3.2/sapi/cli/php_cli.c:1196
(gdb) 

来自扩展名的相关位:

PHP_MINIT_FUNCTION(pp)
{
        // Register PPKeyClient class
        zend_class_entry ce;
        INIT_CLASS_ENTRY(ce, "PPKeyClient", pp_functions);
        PPKeyClient_ce = zend_register_internal_class(&ce TSRMLS_CC);
        PPKeyClient_ce->create_object = PPKeyClient_object_new;
        memcpy(&PPKeyClient_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
        PPKeyClient_handlers.clone_obj = NULL;
        return SUCCESS;
}

zend_object_value PPKeyClient_object_new(zend_class_entry *ce TSRMLS_DC)
{
        zend_object_value retval;
        PPKeyClient_object *intern;

        // TODO - only instantiate look at
        // http://stackoverflow.com/questions/1906565/php-extension-library-accessing-php-superglobals
        // or google for http://www.google.co.uk/search?hl=en&safe=off&q=superglobals+in+php+extensions&aq=f&aqi=&aql=&oq=&gs_rfai=

        intern = ecalloc(1, sizeof(PPKeyClient_object));
        zend_object_std_init(&(intern->std), ce TSRMLS_CC);
        zend_hash_copy(intern->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));

        intern->last_curl_result = PPKC_NO_REQUEST;

        retval.handle = zend_objects_store_put(intern, PPKeyClient_object_dtor, NULL, NULL TSRMLS_CC);
        retval.handlers = &PPKeyClient_handlers;
        return retval;
}

PHP_METHOD(PPKeyClient, __construct)
{
        PPKeyClient_object *intern;
        char *url, *ssl_ca_crt = NULL;
        int port = 80, url_len, ssl_ca_crt_len = 0, ua_len = 0;

        if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &url, &url_len, &port, &ssl_ca_crt, &ssl_ca_crt_len) == SUCCES$
        {
                intern = (PPKeyClient_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
//              intern->port = port;

//              intern->baseurl = estrndup(url, url_len);
//              intern->baseurl_len = url_len;
//              intern->ssl_ca_crt = estrndup(ssl_ca_crt, ssl_ca_crt_len);
//              intern->ssl_ca_crt_len = ssl_ca_crt_len;
//              intern->useragent = "PP KeyClient (PPExt#" PHP_PRIVATE_PASSWORDS_EXTNAME " v" PHP_PRIVATE_PASSWORDS_VERSION ")";
        }
}

我知道对intern = (PPKeyClient_object*)zend_object_store_get_object...行进行注释会使其工作,但显然我不能在没有它的情况下从构造函数中设置值。

我很迷茫,很感激任何帮助找到了什么!

2 个答案:

答案 0 :(得分:0)

我看到一些安装了libsafe的Ubuntu版本,如果Ubuntu 9.04就是这种情况,那么错误总是存在......

这是因为libsafe可以“避免”一些缓冲区溢出,双重释放和其他一些错误。

我不熟悉PHP扩展... getThis()是来自PHP API的函数还是你的?如果它是你的,你能发送吗?

答案 1 :(得分:0)

我不记得究竟是如何解决的 - 我认为@SlappyTheFish是对的 - 与64位有关。我后来重新安装服务器是32位,我相信修复它,所以基本上问题没有解决,但我解决了。