2015-12-29 5 views
6

मैं कुछ पुराने एक्सटेंशन पीएचपी 7. के साथ कामज़ेंड: PHP 7 में कस्टम ऑब्जेक्ट को सही ढंग से कैसे नष्ट करें?

मैं http://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension/ से नमूना विस्तार को संशोधित करने की कोशिश की लेकिन यह segfaults के कारण जब कस्टम वस्तु destructing रखा बनाने के लिए PHP एक्सटेंशन लेखन सीख रहा हूँ। अन्य सभी कार्यों ने सामान्य रूप से काम किया। (कार मेरी कोड में BDict द्वारा बदल दिया गया है।)

यहाँ मेरी कोड है:

#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; 
} 

दो पंक्तियों के अनुक्रम बदल रहा है और $dict = new BDict(10); unset($dict); को क्रियान्वित करने से, मैं उन दोनों के लिए त्रुटि जानकारी पाने में कामयाब रहे।

/***** 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 एक्सटेंशन में नया हूं और अब मैं वास्तव में उलझन में हूं। किसी भी सहायता का स्वागत है, धन्यवाद।

अद्यतन

मैंने देखा है कि वस्तु वास्तव में bdict_free_storage() में रूपांतरण जो स्पष्ट रूप से गलत था के बाद बदल गया है, लेकिन मैं इसे ठीक करने के बारे में पता नहीं था।

यहां डीबग लॉग है। आप देख सकते हैं कि intern और object का डेटा bdict_free_storage() में बिल्कुल अलग है और बीडीक्ट का पता गलत है।

(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}}}}} 

मैं

static void bdict_free_storage(void *object TSRMLS_DC) 

बजाय

static void bdict_free_storage(zend_object *object TSRMLS_DC) 

मैं इसे करने की कोशिश की, लेकिन यह मुझे एक संकलन समय त्रुटि दे दी है का उपयोग करते हुए कुछ अन्य लोगों के मिल गया है।

/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

कैसे: '$ dict = null; अनसेट ($ dict); '? – Hackerman

+0

क्या समस्या यह नहीं है कि आपने 'php_bdict_object_fetch_object' के बजाय' (bdict_object *) ऑब्जेक्ट 'का उपयोग किया है? – NikiC

+1

मैं MINIT में पूरे 'bdict_object_handlers' प्रारंभिकरण को करने का सुझाव भी दूंगा (आप वर्तमान में create_object में दो सदस्यों को असाइन कर रहे हैं) – NikiC

उत्तर

0

"zend_object_handlers bdict_object_handlers" बदलें "zend_object_handlers bdict_object_handlers = std_object_handlers;" इस समस्या को ठीक कर सकते हैं क्योंकि आपने संरचना को प्रारंभ नहीं किया है।

संबंधित मुद्दे