2015-12-29 13 views
6

Bazı eski uzantıları ben http://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension/ örnek uzantısını değiştirmeye çalıştı ancak özel nesne imha edilirken çalışma sırasında parçalama arızası neden tuttuZend: PHP 7'de özel bir nesneyi doğru şekilde nasıl yok edebilirim?

PHP 7. çalışmak kılmak için PHP uzantısı yazma öğreniyorum. Diğer tüm işlevler normal olarak çalıştı. (Araç benim kodunda BDict ile değiştirilir.)

İşte benim kod:

#define Z_BDICT_OBJ_P(zv) php_bdict_object_fetch_object(Z_OBJ_P(zv)) 

zend_object_handlers bdict_object_handlers; 

typedef struct _bdict_object { 
    BDict *bdict_data; 
    zend_object std; 
} bdict_object; 

zend_class_entry *bdict_ce; 

static void bdict_free_storage(zend_object *object TSRMLS_DC) 
{ 
    bdict_object *intern = (bdict_object *)object; 

    // ***Both the following two lines will cause segfault*** 
    delete intern->bdict_data; 
    zend_object_std_dtor(&intern->std TSRMLS_CC); 
} 

zend_object * bdict_object_new(zend_class_entry *ce TSRMLS_DC) 
{ 
    bdict_object *intern = (bdict_object *)ecalloc(1, 
      sizeof(bdict_object) + 
      zend_object_properties_size(ce)); 

    zend_object_std_init(&intern->std, ce TSRMLS_CC); 
    object_properties_init(&intern->std, ce); 

    intern->std.handlers = &bdict_object_handlers; 

    return &intern->std; 
} 

static inline bdict_object * php_bdict_object_fetch_object(zend_object *obj) 
{ 
    return (bdict_object *)((char *)obj - XtOffsetOf(bdict_object, std)); 
} 

PHP_METHOD(BDict, __construct) 
{ 
    long maxGear; 
    BDict *bdict = NULL; 

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxGear) == FAILURE) { 
     RETURN_NULL(); 
    } 

    bdict = new BDict(maxGear); 
    bdict_object *intern = Z_BDICT_OBJ_P(getThis()); 
    intern->bdict_data = bdict; 
} 

PHP_MINIT_FUNCTION(bencode) 
{ 
    zend_class_entry ce; 
    INIT_CLASS_ENTRY(ce, "BDict", bdict_methods); 
    bdict_ce = zend_register_internal_class(&ce TSRMLS_CC); 
    bdict_ce->create_object = bdict_object_new; 

    memcpy(&bdict_object_handlers, 
      zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 

    bdict_object_handlers.offset = XtOffsetOf(bdict_object, std); 
    bdict_object_handlers.free_obj = bdict_free_storage; 

    return SUCCESS; 
} 

iki satır sırasını değiştirerek ve $dict = new BDict(10); unset($dict); yürütme, ben ikisi için hata bilgilerini başardı.

/***** delete intern->bdict_data; *****/ 
Starting program: /opt/php-7.0.1/bin/php test.php 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 

Program received signal SIGSEGV, Segmentation fault. 
__GI___libc_free (mem=0xc002180800000001) at malloc.c:2933 

/***** zend_object_std_dtor(&intern->std TSRMLS_CC); *****/ 
Starting program: /opt/php-7.0.1/bin/php test.php 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000a45890 in zend_object_std_dtor (object=0x7ffff4001c90) at /home/frederick/php-7.0.1/Zend/zend_objects.c:59 
59      if (EXPECTED(!(GC_FLAGS(object->properties) & IS_ARRAY_IMMUTABLE))) { 

PHP uzantılarına yeniyim ve şimdi gerçekten kafam karıştı. Herhangi bir yardım büyük, teşekkürler duyacağız.

GÜNCELLEME

Ben nesne aslında açıkça yanlış olduğunu bdict_free_storage() dönüşüm sonra değişti fark ama bunu düzeltme hakkında hiçbir fikri yoktu.

İşte hata ayıklama günlüğü. intern ve object verilerinin bdict_free_storage()'daki verilerin tamamen farklı olduğunu ve BDict adresinin yanlış olduğunu görebilirsiniz.

(gdb) b bencode.cc:20 // bdict_free_storage():   bdict_object *intern = (bdict_object *)object; 
Breakpoint 1 at 0x7ffff36de608: file /home/frederick/php-7.0.1/ext/php-bencode/bencode.cc, line 20. 
(gdb) b bencode.cc:54 // PHP_METHOD(BDict, __construct): intern->bdict_data = bdict; 
Breakpoint 2 at 0x7ffff36de77e: file /home/frederick/php-7.0.1/ext/php-bencode/bencode.cc, line 54. 
(gdb) r 
Starting program: /opt/php-7.0.1/bin/php test.php 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 

Breakpoint 2, zim_BDict___construct (execute_data=0x7ffff40140d0, return_value=0x7ffff40140b0) at /home/frederick/php-7.0.1/ext/php-bencode/bencode.cc:54 
54   intern->bdict_data = bdict; 
(gdb) n 
55  } 
(gdb) p intern->bdict_data 
$1 = (BDict *) 0x150c530 
(gdb) c 
Continuing. 

Breakpoint 1, bdict_free_storage (object=0x7ffff4001c88) at /home/frederick/php-7.0.1/ext/php-bencode/bencode.cc:20 
20   bdict_object *intern = (bdict_object *)object; 
(gdb) n 
21   zend_object_std_dtor(&intern->std TSRMLS_CC); 
(gdb) p *object  // type = 8 means IS_OBJECT 
$2 = {gc = {refcount = 1, u = {v = {type = 8 '\b', flags = 24 '\030', gc_info = 49154}, type_info = 3221362696}}, handle = 1, ce = 0x14fe6e0, 
    handlers = 0x7ffff38e0300 <bdict_object_handlers>, properties = 0x0, properties_table = {{value = {lval = 48, dval = 2.3715151000379834e-322, counted = 0x30, str = 0x30, arr = 0x30, 
     obj = 0x30, res = 0x30, ref = 0x30, ast = 0x30, zv = 0x30, ptr = 0x30, ce = 0x30, func = 0x30, ww = {w1 = 48, w2 = 0}}, u1 = {v = {type = 232 '\350', type_flags = 237 '\355', 
      const_flags = 109 'm', reserved = 243 '\363'}, type_info = 4084067816}, u2 = {var_flags = 32767, next = 32767, cache_slot = 32767, lineno = 32767, num_args = 32767, 
     fe_pos = 32767, fe_iter_idx = 32767}}}} 
(gdb) p *intern  // type = 0 means IS_UNDEF, all other data are also different 
$3 = {bdict_data = 0xc002180800000001, std = {gc = {refcount = 1, u = {v = {type = 0 '\000', flags = 0 '\000', gc_info = 0}, type_info = 0}}, handle = 22013664, 
    ce = 0x7ffff38e0300 <bdict_object_handlers>, handlers = 0x0, properties = 0x30, properties_table = {{value = {lval = 140737277455848, dval = 6.9533453880162249e-310, 
      counted = 0x7ffff36dede8, str = 0x7ffff36dede8, arr = 0x7ffff36dede8, obj = 0x7ffff36dede8, res = 0x7ffff36dede8, ref = 0x7ffff36dede8, ast = 0x7ffff36dede8, zv = 0x7ffff36dede8, 
      ptr = 0x7ffff36dede8, ce = 0x7ffff36dede8, func = 0x7ffff36dede8, ww = {w1 = 4084067816, w2 = 32767}}, u1 = {v = {type = 0 '\000', type_flags = 131 '\203', 
      const_flags = 3 '\003', reserved = 1 '\001'}, type_info = 17007360}, u2 = {var_flags = 0, next = 0, cache_slot = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0}}}}} 

Ben

static void bdict_free_storage(void *object TSRMLS_DC) 

yerine ben denedim ama bana derleme zamanı hata verdi

static void bdict_free_storage(zend_object *object TSRMLS_DC) 

kullanarak bazı diğerlerini buldum.

/home/frederick/php-7.0.1/ext/php-bencode/bencode.cc: In function ‘int zm_startup_bencode(int, int)’: 
/home/frederick/php-7.0.1/ext/php-bencode/bencode.cc:131:36: error: invalid conversion from ‘void (*)(void*)’ to ‘zend_object_free_obj_t {aka void (*)(_zend_object*)}’ [-fpermissive] 
    bdict_object_handlers.free_obj = bdict_free_storage; 
+0

Ne dersin: '$ dict = null; unset ($ dict); '? – Hackerman

+0

Sorun sadece 'php_bdict_object_fetch_object' yerine '(bdict_object *) nesnesi' kullandığınız değil mi? – NikiC

+1

Ayrıca MINIT içinde tüm bdict_object_handlers 'başlatmayı (şu anda create_object içinde iki üye atamaktasınız) önermek isterim – NikiC

cevap

0

"zend_object_handlers bdict_object_handlers;" "zend_object_handlers bdict_object_handlers = std_object_handlers"; yapıyı başlatmamış olduğunuzdan bu sorunu çözebilir.

İlgili konular