C 中的自定义 PHP 扩展中的段错误实例化类
我正在开发自己的 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...
行可以使其工作,但显然我如果没有它,就无法从构造函数中设置值。
我很迷茫,希望能得到任何帮助来了解情况!
I'm developing my own PHP extension with a class in it. I recently upgraded from Ubuntu 9.04 to 9.10 and the extension broke. I since tried to update to 10.04 to see if it fixes it as my dev environment is 10.04 and it works fine on there. The only major difference from what I can understand is the server is 64 bit and my laptop 32 bit architecture. I have PHP version 5.3.2-1ubuntu4.5 (Zend build 20090626).
I have tried running my test PHP file:
<?php $server = "http://localhost/"; $port = 1214; $f = new PPKeyClient($server, $port); var_dump($f);
In 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)
And the relevant bits from the extension:
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 ")"; } }
I know that commenting the intern = (PPKeyClient_object*)zend_object_store_get_object...
line makes it work, but obviously I can't set the values from the constructor without that.
I'm so lost and would appreciate any help finding what's up!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我看到一些 Ubuntu 版本安装了 libsafe,如果 Ubuntu 9.04 是这种情况,也许错误总是存在......
这是因为 libsafe 可以“避免”一些缓冲区溢出、双重释放和其他一些错误。
我不熟悉 PHP 扩展... getThis() 是 PHP API 中的函数还是您的函数?如果是你的,你能寄给我吗?
I saw some Ubuntu versions that brings libsafe installed, if this was the case with Ubuntu 9.04 maybe the error was always there...
It is because libsafe can "avoid" some buffer overflows, double free and some other bugs.
I'm not familiar with PHP extensions... is getThis() a function from the PHP API or is yours? if it's yours can you send it?
我不记得我是如何解决这个问题的 - 我认为@SlappyTheFish 是对的 - 与 64 位有关。后来我将服务器重新安装为 32 位,我相信问题已经解决,所以本质上问题没有解决,但我解决了它。
I can't remember exactly how I fixed this - I think @SlappyTheFish was right - something to do with 64 bitness. I later re-installed the server to be 32-bit and I believe that fixed it, so essentially the problem wasn't solved but I worked around it.