Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP扩展-带有PHP版本编译的Segfault_Php_C++_C_Segmentation Fault_Php Extension - Fatal编程技术网

PHP扩展-带有PHP版本编译的Segfault

PHP扩展-带有PHP版本编译的Segfault,php,c++,c,segmentation-fault,php-extension,Php,C++,C,Segmentation Fault,Php Extension,我已经写了一个PHP扩展,现在我真的很奇怪 如果我通过php test.php或phpce->name), ZSTR_LEN(对象)->ce->name) 这也是防撞的 此外,您还使函数的开头变得复杂: char*ini_ns_key=estrdup(“bencode.namespace”); zend_bool ini_ns=zend_ini_long(ini_ns_键,strlen(ini_ns_键),0); efree(ini键) 应该这样写: zend_long ini_ns_long=

我已经写了一个PHP扩展,现在我真的很奇怪

如果我通过
php test.php
php
运行测试脚本是可以的,但是如果我在交互模式下输入完全相同的命令(
php-a
),则会出现segfault

46              char *_class_name = (char *)emalloc(_class_name_len);
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x000055555578f664 in _emalloc ()
首先,我认为从Launchpad复制PHP二进制文件可能会有一些问题,我编译了自己的一个。configure命令是
。/configure'--前缀=/opt/php7 dbg'--使用gd'--使用mysqli'--使用readline'--使用curl'
。(优化器参数为
-O2

我又遇到了完全相同的问题,但这次我可以更进一步

46              char *_class_name = (char *)emalloc(_class_name_len);
(gdb) s
_emalloc (size=4) at /home/frederick/Programming/C/php-7.0.6/Zend/zend_alloc.c:2439
2439    {
(gdb) n
2442            if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
(gdb) n
2450            return zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
(gdb) s
zend_mm_alloc_heap (size=4, heap=0x7fffef000040) at /home/frederick/Programming/C/php-7.0.6/Zend/zend_alloc.c:1365
1365            if (size <= ZEND_MM_MAX_SMALL_SIZE) {
(gdb) n
1366                    ptr = zend_mm_alloc_small(heap, size, ZEND_MM_SMALL_SIZE_TO_BIN(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
(gdb) s
zend_mm_small_size_to_bin (size=4) at /home/frederick/Programming/C/php-7.0.6/Zend/zend_alloc.c:1211
1211            if (size <= 64) {
(gdb) n
1213                    return (size - !!size) >> 3;
(gdb) s
zend_mm_alloc_heap (size=<optimised out>, heap=0x7fffef000040) at /home/frederick/Programming/C/php-7.0.6/Zend/zend_alloc.c:1366
1366                    ptr = zend_mm_alloc_small(heap, size, ZEND_MM_SMALL_SIZE_TO_BIN(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
(gdb) s
zend_mm_alloc_small (bin_num=<optimised out>, size=<optimised out>, heap=0x7fffef000040) at /home/frederick/Programming/C/php-7.0.6/Zend/zend_alloc.c:1286
1286                    size_t size = heap->size + bin_data_size[bin_num];
(gdb) n
1287                    size_t peak = MAX(heap->peak, size);
(gdb) n
1288                    heap->size = size;
(gdb) n
1289                    heap->peak = peak;
(gdb) n
1293            if (EXPECTED(heap->free_slot[bin_num] != NULL)) {
(gdb) n
1295                    heap->free_slot[bin_num] = p->next_free_slot;
(gdb) p bin_num
$1 = <optimised out>
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
zend_mm_alloc_small (bin_num=<optimised out>, size=<optimised out>, heap=0x7fffef000040) at /home/frederick/Programming/C/php-7.0.6/Zend/zend_alloc.c:1295
1295                    heap->free_slot[bin_num] = p->next_free_slot;
然后我知道是哪条线路产生了SEGFULT,我想解决这个问题。因此,我立即编译了一个PHP调试版本(configure命令:
'./configure'.-prefix=/opt/php7 dbg'.-with-gd'.-with-mysqli'.-with-readline'.-with-curl'.-enable debug'
,优化器:
-O0

但是,在基于相同代码的调试构建中,segfault就消失了

我不是一个经验丰富的C/C++开发人员,这是我第一次遇到这样的问题。请帮忙,非常感谢

更新

看来这个问题是由一个愚蠢的错误引起的。导致SEG故障的线路应

char *_class_name = (char *)emalloc(_class_name_len + 1);
as C字符串应以“\0”结尾


但是为什么调试版本可以呢?

我猜您的程序在
strcpy
处崩溃,
emalloc
行只是崩溃前的最后一行。这里确实有一个错误,需要向emalloc添加+1,因为字符串末尾有0字节

但你把事情弄得太复杂了。因为你使用C++,你可以用一行替换所有的从sisivit到EFELE(包括它们)的行:

std::string class_name(ZSTR_VAL(Z_OBJ_p(object)->ce->name),
ZSTR_LEN(对象)->ce->name)

这也是防撞的

此外,您还使函数的开头变得复杂:

char*ini_ns_key=estrdup(“bencode.namespace”);
zend_bool ini_ns=zend_ini_long(ini_ns_键,strlen(ini_ns_键),0);
efree(ini键)

应该这样写:

zend_long ini_ns_long=zend_ini_long(“bencode.namespace”),strlen(“bencode.namespace”),0;

bool ini_ns=(ini_ns_long!=0)

我猜您的程序在
strcpy
处崩溃,
emalloc
行只是崩溃前的最后一行。这里确实有一个错误,需要向emalloc添加+1,因为字符串末尾有0字节

但你把事情弄得太复杂了。因为你使用C++,你可以用一行替换所有的从sisivit到EFELE(包括它们)的行:

std::string class_name(ZSTR_VAL(Z_OBJ_p(object)->ce->name),
ZSTR_LEN(对象)->ce->name)

这也是防撞的

此外,您还使函数的开头变得复杂:

char*ini_ns_key=estrdup(“bencode.namespace”);
zend_bool ini_ns=zend_ini_long(ini_ns_键,strlen(ini_ns_键),0);
efree(ini键)

应该这样写:

zend_long ini_ns_long=zend_ini_long(“bencode.namespace”),strlen(“bencode.namespace”),0;

bool ini_ns=(ini_ns_long!=0)

很有趣。昨晚我看了一会儿,没有发现任何惊人的错误。我仍然不相信你的解决方案真的解决了这个问题。据我所知,
emalloc
不知道它正在为字符串分配空间,需要为
'\0'
分配空间。这是一个奇怪的事实,它的seg断层。根据我的经验,打开优化会暴露出在关闭优化时没有发现的问题。我敢打赌,在调用
emalloc
时,您的代码中有一些UB未显示,并且出于任何原因,它会暴露出来。
zend\u
函数是您的吗?什么是zval?宏是什么?@yano谢谢你的回答!这些宏大多来自PHP,PHP通过
#define emalloc(size)_emalloc((size)ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
定义了自己的
emalloc
。更重要的是,PHP
emalloc
将根据许多因素(无论是调试,还是在Windows下,或者使用clang等)表现不同。这相当复杂,我不确定问题从何而来。也许你需要PHP的源代码,呃,我对
PHP
一无所知。这是您发布的唯一的
c++
调用的
c++
函数,还是从其他
c++
调用的未发布代码?感谢您指出
php
有一个
emalloc
函数,我想知道为什么您的
gdb
进入
emalloc
看起来与
c
版本完全不同:@yano它只是整个扩展的一部分。仅供参考,您可以在PHP中的第2400行找到
emalloc
。昨晚我看了一会儿,没有发现任何惊人的错误。我仍然不相信你的解决方案真的解决了这个问题。据我所知,
emalloc
不知道它正在为字符串分配空间,需要为
'\0'
分配空间。这是一个奇怪的事实,它的seg断层。根据我的经验,打开优化会暴露出在关闭优化时没有发现的问题。我敢打赌,在调用
emalloc
时,您的代码中有一些UB未显示,并且出于任何原因,它会暴露出来。
zend\u
函数是您的吗?什么是zval?宏是什么?@yano谢谢你的回答!这些宏大多来自PHP,PHP通过
#define emalloc(size)_emalloc((size)ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
定义了自己的
emalloc
。更重要的是,PHP
emalloc
的行为将因具体情况而有所不同
char *_class_name = (char *)emalloc(_class_name_len + 1);