访问迭代器中的当前数据时出现分段故障ZVAL_STR()



我想知道是否有人能帮我。我一直在为谷歌稀疏shmap开发php扩展,我一直在按我的意愿/需要进行扩展,除了迭代。

几个星期以来,我一直在绞尽脑汁,试图使用迭代器中内置的类来让它发挥作用。

根据我对测试文件所做的回溯,这就是SIGSEGV被抛出的地方

static zval* php_sparsehashmap_iterator_current_data(php_sparsehashmap_iterator_t *iterator) {
php_sparsehashmap_iterator_t *io = (php_sparsehashmap_iterator_t*)iterator;
zend_string *_data;
zval *data;
_php_sparsehashmap_t *sp = PHP_SPARSEHASHMAP_FETCH_FROM(Z_OBJ(io->sparsehashmap));
std::string current_data = sp->shm->current_data();
_data = zend_string_init(current_data.c_str(), strlen(current_data.c_str()), 0);
ZVAL_STR(data, _data);
return data;
}

当我运行测试文件时,这就是GDB给我的。

Program received signal SIGSEGV, Segmentation fault.
php_sparsehashmap_iterator_current_data (iterator=<optimized out>) at php-sparsehashmap/iterator.cc:58
58      ZVAL_STR(data, _data);
(gdb) bt
#0  php_sparsehashmap_iterator_current_data (iterator=<optimized out>) at php-sparsehashmap/iterator.cc:58
#1  0x000055555586d215 in ?? ()
#2  0x0000555555875daf in execute_ex ()
#3  0x000055555587da21 in zend_execute ()
#4  0x00005555557f6963 in zend_execute_scripts ()
#5  0x0000555555795cc0 in php_execute_script ()
#6  0x000055555587fb56 in ?? ()
#7  0x000055555565bebb in ?? ()
#8  0x00007ffff764109b in __libc_start_main (main=0x55555565ba70, argc=2, argv=0x7fffffffe5d8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe5c8)
at ../csu/libc-start.c:308
#9  0x000055555565c01a in _start ()

为了更好地了解Segmentation Fault发生时发生的情况,我使用valgrind运行,并设置了选项--leak-check=full--track-origin=yes

==15401== Invalid write of size 8
==15401==    at 0xA1743D3: php_sparsehashmap_iterator_current_data(_php_sparsehashmap_iterator_t*) (iterator.cc:67)
==15401==    by 0x421214: ??? (in /usr/bin/php7.4)
==15401==    by 0x429DAE: execute_ex (in /usr/bin/php7.4)
==15401==    by 0x431A20: zend_execute (in /usr/bin/php7.4)
==15401==    by 0x3AA962: zend_execute_scripts (in /usr/bin/php7.4)
==15401==    by 0x349CBF: php_execute_script (in /usr/bin/php7.4)
==15401==    by 0x433B55: ??? (in /usr/bin/php7.4)
==15401==    by 0x20FEBA: ??? (in /usr/bin/php7.4)
==15401==    by 0x505B09A: (below main) (libc-start.c:308)
==15401==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==15401== 
==15401== 
==15401== Process terminating with default action of signal 11 (SIGSEGV)
==15401==  Access not within mapped region at address 0x0
==15401==    at 0xA1743D3: php_sparsehashmap_iterator_current_data(_php_sparsehashmap_iterator_t*) (iterator.cc:67)
==15401==    by 0x421214: ??? (in /usr/bin/php7.4)
==15401==    by 0x429DAE: execute_ex (in /usr/bin/php7.4)
==15401==    by 0x431A20: zend_execute (in /usr/bin/php7.4)
==15401==    by 0x3AA962: zend_execute_scripts (in /usr/bin/php7.4)
==15401==    by 0x349CBF: php_execute_script (in /usr/bin/php7.4)
==15401==    by 0x433B55: ??? (in /usr/bin/php7.4)
==15401==    by 0x20FEBA: ??? (in /usr/bin/php7.4)
==15401==    by 0x505B09A: (below main) (libc-start.c:308)
==15401==  If you believe this happened as a result of a stack
==15401==  overflow in your program's main thread (unlikely but
==15401==  possible), you can try to increase the size of the
==15401==  main thread stack using the --main-stacksize= flag.
==15401==  The main thread stack size used in this run was 8388608.
==15401== 
==15401== HEAP SUMMARY:
==15401==     in use at exit: 3,367,736 bytes in 26,417 blocks
==15401==   total heap usage: 128,270 allocs, 101,853 frees, 22,900,347 bytes allocated
==15401== 
==15401== LEAK SUMMARY:
==15401==    definitely lost: 96 bytes in 4 blocks
==15401==    indirectly lost: 0 bytes in 0 blocks
==15401==      possibly lost: 2,338,288 bytes in 18,657 blocks
==15401==    still reachable: 1,029,352 bytes in 7,756 blocks
==15401==         suppressed: 0 bytes in 0 blocks

为了让事情变得更容易一点,我上传到了一个git repo,以便对代码以及在这个Github repo中可以找到的必需类进行完全可见性。

我知道它看起来并不100%令人惊讶,这是我第一次尝试C/C++/php扩展,所以在构建它的过程中我学到了很多。

提前感谢,如有任何帮助,我们将不胜感激。

问题是data指向未初始化的内存。你需要实际上在某个地方有一个zval,它通常在CCD_ 6结构。

static zval* php_<extension_iterator_name>_current_data需要zval*返回,但不能返回内部函数变量,因为它不会在函数范围之外初始化。

相反,在迭代器结构中创建一个zval变量,在<extension_iterator_name>_current_data()函数中返回迭代器zval的值。即

/* {{{ */
typedef struct _php_sparsehashmap_iterator_t {
zend_object_iterator it;
zval zdata;
zend_long pos;
} php_sparsehashmap_iterator_t; /* }}} */
/* {{{ */
zend_object_iterator* php_sparsehashmap_iterator(zend_class_entry *ce, zval *sparsehashmap, int by_ref) {
zend_string *_data;
php_sparsehashmap_iterator_t *io = (php_sparsehashmap_iterator_t*) emalloc(sizeof(php_sparsehashmap_iterator_t));
zend_iterator_init((zend_object_iterator*) io);
io->pos = 0;
io->it.funcs = &php_sparsehashmap_iterator_funcs;
std::string current_data = get_current_data();
_data = zend_string_init(current_data.c_str(), strlen(current_data.c_str()), 0);
ZVAL_STR(&io->zdata, _data);
return (zend_object_iterator*) io;
} /* }}} */
static zval* php_sparsehashmap_iterator_current_data(php_sparsehashmap_iterator_t *iterator) {
php_sparsehashmap_iterator_t *io = (php_sparsehashmap_iterator_t*)iterator;
return &io->zdata;
}

最新更新