]> granicus.if.org Git - php/commitdiff
- MFH debug object helper
authorMarcus Boerger <helly@php.net>
Thu, 11 Oct 2007 01:03:19 +0000 (01:03 +0000)
committerMarcus Boerger <helly@php.net>
Thu, 11 Oct 2007 01:03:19 +0000 (01:03 +0000)
Zend/zend.c
Zend/zend_object_handlers.c
Zend/zend_object_handlers.h
Zend/zend_operators.h
ext/simplexml/simplexml.c
ext/standard/var.c

index 1921b07a3fabc2961c99736c157d58b6e4679912..e7767ceadf07eff23be5e6d5ef45fc31bf8d19f7 100644 (file)
@@ -317,7 +317,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC)
                        HashTable *properties = NULL;
                        char *class_name = NULL;
                        zend_uint clen;
-                       
+
                        if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
                                Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
                        }
@@ -367,10 +367,11 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
                        break;
                case IS_OBJECT:
                        {
-                               HashTable *properties = NULL;
+                               HashTable *properties;
                                char *class_name = NULL;
                                zend_uint clen;
-                               
+                               int is_temp;
+
                                if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
                                        Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
                                }
@@ -383,17 +384,19 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
                                if (class_name) {
                                        efree(class_name);
                                }
-                               if (Z_OBJ_HANDLER_P(expr, get_properties)) {
-                                       properties = Z_OBJPROP_P(expr);
+                               if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
+                                       break;
                                }
-                               if (properties) {
-                                       if (++properties->nApplyCount>1) {
-                                               ZEND_PUTS_EX(" *RECURSION*");
-                                               properties->nApplyCount--;
-                                               return;
-                                       }
-                                       print_hash(write_func, properties, indent, 1 TSRMLS_CC);
+                               if (++properties->nApplyCount>1) {
+                                       ZEND_PUTS_EX(" *RECURSION*");
                                        properties->nApplyCount--;
+                                       return;
+                               }
+                               print_hash(write_func, properties, indent, 1 TSRMLS_CC);
+                               properties->nApplyCount--;
+                               if (is_temp) {
+                                       zend_hash_destroy(properties);
+                                       efree(properties);
                                }
                                break;
                        }
@@ -711,7 +714,7 @@ void zend_post_startup(TSRMLS_D)
        short_tags_default = CG(short_tags);
        ct_pass_ref_default = CG(allow_call_time_pass_reference);
        extended_info_default = CG(extended_info);
-       
+
        zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
        free(compiler_globals->function_table);
        free(compiler_globals->class_table);
@@ -839,7 +842,7 @@ void zend_deactivate_modules(TSRMLS_D)
        } zend_end_try();
 }
 
-void zend_call_destructors(TSRMLS_D) 
+void zend_call_destructors(TSRMLS_D)
 {
        zend_try {
                shutdown_destructors(TSRMLS_C);
@@ -1026,11 +1029,11 @@ ZEND_API void zend_error(int type, const char *format, ...)
 
                        orig_user_error_handler = EG(user_error_handler);
                        EG(user_error_handler) = NULL;
-                       
+
                        /* User error handler may include() additinal PHP files.
                         * If an error was generated during comilation PHP will compile
-                        * such scripts recursivly, but some CG() variables may be 
-                        * inconsistent. */ 
+                        * such scripts recursivly, but some CG() variables may be
+                        * inconsistent. */
 
                        in_compilation = zend_is_compiling(TSRMLS_C);
                        if (in_compilation) {
@@ -1056,7 +1059,7 @@ ZEND_API void zend_error(int type, const char *format, ...)
 
                        if (!EG(user_error_handler)) {
                                EG(user_error_handler) = orig_user_error_handler;
-                       } 
+                       }
                        else {
                                zval_ptr_dtor(&orig_user_error_handler);
                        }
index e0260c1a655660f8c0fcc73123c5ff9681a836ed..b71df7c8ecae9a02a419ea09dced2faad8039faa 100644 (file)
   set, we call __set handler. If it fails, we do not change the array.
 
   for both handlers above, when we are inside __get/__set, no further calls for
-  __get/__set for this property of this object will be made, to prevent endless 
+  __get/__set for this property of this object will be made, to prevent endless
   recursion and enable accessors to change properties array.
 
   if we have __call and method which is not part of the class function table is
   called, we cal __call handler.
 */
 
-static HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
+ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
 {
        zend_object *zobj;
        zobj = Z_OBJ_P(object);
@@ -316,7 +316,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
 
 #if DEBUG_OBJECT_HANDLERS
        fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
-#endif                 
+#endif
 
        /* make zend_get_property_info silent if we have getter - we may want to use it */
        property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC);
@@ -758,11 +758,11 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
        zend_function *fbc;
        char *lc_method_name;
        zval *object = *object_ptr;
-       
+
        lc_method_name = do_alloca(method_len+1);
        /* Create a zend_copy_str_tolower(dest, src, src_length); */
        zend_str_tolower_copy(lc_method_name, method_name, method_len);
-               
+
        zobj = Z_OBJ_P(object);
        if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
                free_alloca(lc_method_name);
@@ -830,7 +830,7 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
        zval *method_name_ptr, *method_args_ptr;
        zval *method_result_ptr = NULL;
        zend_class_entry *ce = EG(scope);
+
        ALLOC_ZVAL(method_args_ptr);
        INIT_PZVAL(method_args_ptr);
        array_init(method_args_ptr);
@@ -883,7 +883,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
                        callstatic_user_call->arg_info = NULL;
                        callstatic_user_call->num_args = 0;
                        callstatic_user_call->scope    = ce;
-                       callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC; 
+                       callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC;
                        callstatic_user_call->function_name = estrndup(function_name_strval, function_name_strlen);
                        callstatic_user_call->pass_rest_by_reference = 0;
                        callstatic_user_call->return_reference       = ZEND_RETURN_VALUE;
@@ -1202,6 +1202,7 @@ ZEND_API zend_object_handlers std_object_handlers = {
        zend_std_compare_objects,                               /* compare_objects */
        zend_std_cast_object_tostring,                  /* cast_object */
        NULL,                                                                   /* count_elements */
+       NULL,                                   /* get_debug_info */
 };
 
 /*
index 8c27ae6340842d68d6791acdfbf1d7134f98da8e..83dd72356cc825c2acb808a430e97e2f4e52e4fa 100644 (file)
@@ -80,6 +80,8 @@ typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_
 /* Used to get hash of the properties of the object, as hash of zval's */
 typedef HashTable *(*zend_object_get_properties_t)(zval *object TSRMLS_DC);
 
+typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp TSRMLS_DC);
+
 /* Used to call methods */
 /* args on stack! */
 /* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this.
@@ -132,6 +134,7 @@ struct _zend_object_handlers {
        zend_object_compare_t                                   compare_objects;
        zend_object_cast_t                                              cast_object;
        zend_object_count_elements_t                    count_elements;
+       zend_object_get_debug_info_t                    get_debug_info;
 };
 
 extern ZEND_API zend_object_handlers std_object_handlers;
@@ -143,6 +146,8 @@ ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *pr
 ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC);
 ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC);
 
+ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
+ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC);
 ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
 
 
index c20c57088c3a5ba5118d6833668c5534291b70cf..f5c6251ca795450f0d24af3b32a784f7f3a7e849 100644 (file)
@@ -387,6 +387,7 @@ END_EXTERN_C()
 #define Z_OBJPROP(zval)                        Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
 #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
 #define Z_RESVAL(zval)                 (zval).value.lval
+#define Z_OBJDEBUG(zval,is_tmp)        (Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
 
 #define Z_LVAL_P(zval_p)               Z_LVAL(*zval_p)
 #define Z_BVAL_P(zval_p)               Z_BVAL(*zval_p)
@@ -401,6 +402,7 @@ END_EXTERN_C()
 #define Z_OBJ_HANDLE_P(zval_p)  Z_OBJ_HANDLE(*zval_p)
 #define Z_OBJ_HT_P(zval_p)      Z_OBJ_HT(*zval_p)
 #define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h)
+#define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp)
 
 #define Z_LVAL_PP(zval_pp)             Z_LVAL(**zval_pp)
 #define Z_BVAL_PP(zval_pp)             Z_BVAL(**zval_pp)
@@ -415,6 +417,7 @@ END_EXTERN_C()
 #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
 #define Z_OBJ_HT_PP(zval_p)     Z_OBJ_HT(**zval_p)
 #define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h)
+#define Z_OBJDEBUG_PP(zval_pp,is_tmp) Z_OBJDEBUG(**zval_pp,is_tmp)
 
 #define Z_TYPE(zval)           (zval).type
 #define Z_TYPE_P(zval_p)       Z_TYPE(*zval_p)
index c847df27b3e96cec564a8c9d856f008424990edc..734c593df8abcca6edf121f747474822d506b9c6 100644 (file)
@@ -136,7 +136,7 @@ static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name,
 static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xmlNodePtr node, long *cnt) /* {{{ */
 {
        long nodendx = 0;
-       
+
        if (sxe->iter.type == SXE_ITER_NONE) {
                if (offset == 0) {
                        if (cnt) {
@@ -161,7 +161,7 @@ static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xm
 next_iter:
                node = node->next;
        }
-       
+
        if (cnt) {
                *cnt = nodendx;
        }
@@ -275,7 +275,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements,
 
        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                attribs = 1;
-               elements = 0;           
+               elements = 0;
                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                attr = (xmlAttrPtr)node;
                test = sxe->iter.name != NULL;
@@ -337,7 +337,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements,
                                        }
                                } else if (member) {
                                        node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
-                               } else {                                        
+                               } else {
                                        node = NULL;
                                }
                                if (node) {
@@ -502,7 +502,7 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo
 
        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                attribs = 1;
-               elements = 0;           
+               elements = 0;
                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                attr = (xmlAttrPtr)node;
                test = sxe->iter.name != NULL;
@@ -639,7 +639,7 @@ next_iter:
                        if (!node) {
                                if (!member || Z_TYPE_P(member) == IS_LONG) {
                                        newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
-                               } else {                                
+                               } else {
                                        newnode = xmlNewTextChild(mynode, mynode->ns, (xmlChar *)Z_STRVAL_P(member), value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
                                }
                        } else if (!member || Z_TYPE_P(member) == IS_LONG) {
@@ -711,6 +711,9 @@ static zval** sxe_property_get_adr(zval *object, zval *member TSRMLS_DC) /* {{{
        _node_as_zval(sxe, node, return_value, type, name, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
 
        sxe = php_sxe_fetch_object(return_value TSRMLS_CC);
+       if (sxe->tmp) {
+               zval_ptr_dtor(&sxe->tmp);
+       }
        sxe->tmp = return_value;
        Z_SET_ISREF_P(return_value);
 
@@ -752,7 +755,7 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
 
        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                attribs = 1;
-               elements = 0;           
+               elements = 0;
                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                attr = (xmlAttrPtr)node;
                test = sxe->iter.name != NULL;
@@ -814,7 +817,7 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
                        }
                        if (node) {
                                exists = 1;
-                                if (check_empty == 1 && 
+                                if (check_empty == 1 &&
                                        (!node->children || (node->children->type == XML_TEXT_NODE && !node->children->next &&
                                                (!node->children->content || !node->children->content[0] || !xmlStrcmp(node->children->content, "0")))) ) {
                                        exists = 0;
@@ -882,7 +885,7 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements,
 
        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                attribs = 1;
-               elements = 0;           
+               elements = 0;
                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                attr = (xmlAttrPtr)node;
                test = sxe->iter.name != NULL;
@@ -978,7 +981,7 @@ static inline char * sxe_xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, in
        char    *res = estrdup((char*)tmp);
 
        xmlFree(tmp);
-       
+
        return res;
 }
 
@@ -1038,9 +1041,9 @@ static void sxe_properties_add(HashTable *rv, char *name, int namelen, zval *val
        }
 }
 
-/* {{{ sxe_properties_get()
+/* {{{ sxe_get_prop_hash()
  */
-static HashTable * sxe_properties_get(zval *object TSRMLS_DC)
+static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{{ */
 {
        zval            *value;
        zval            *zattr;
@@ -1054,7 +1057,11 @@ static HashTable * sxe_properties_get(zval *object TSRMLS_DC)
 
        sxe = php_sxe_fetch_object(object TSRMLS_CC);
 
-       if (sxe->properties) {
+       if (is_debug) {
+               ALLOC_HASHTABLE(rv);
+               zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
+       }
+       else if (sxe->properties) {
                zend_hash_clean(sxe->properties);
                rv = sxe->properties;
        } else {
@@ -1067,7 +1074,7 @@ static HashTable * sxe_properties_get(zval *object TSRMLS_DC)
        if (!node) {
                return rv;
        }
-       if (1||sxe->iter.type != SXE_ITER_CHILD) {
+       if (is_debug) {
                if (sxe->iter.type == SXE_ITER_ELEMENT) {
                        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                }
@@ -1137,6 +1144,19 @@ next_iter:
 }
 /* }}} */
 
+static HashTable * sxe_get_properties(zval *object TSRMLS_DC) /* {{{ */
+{
+       return sxe_get_prop_hash(object, 0 TSRMLS_CC);
+}
+/* }}} */
+
+static HashTable * sxe_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
+{
+       *is_temp = 1;
+       return sxe_get_prop_hash(object, 1 TSRMLS_CC);
+}
+/* }}} */
+
 static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{ */
 {
        php_sxe_object *sxe1;
@@ -1365,13 +1385,13 @@ static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool r
 {
        xmlAttrPtr  attr;
 
-       if (node->ns) { 
+       if (node->ns) {
                sxe_add_namespace_name(return_value, node->ns);
        }
 
        attr = node->properties;
        while (attr) {
-               if (attr->ns) { 
+               if (attr->ns) {
                        sxe_add_namespace_name(return_value, attr->ns);
                }
                attr = attr->next;
@@ -1521,7 +1541,7 @@ SXE_METHOD(attributes)
 
        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
        GET_NODE(sxe, node);
-       
+
        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                return; /* attributes don't have attributes */
        }
@@ -1565,7 +1585,7 @@ SXE_METHOD(addChild)
 
        if (node == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
-               return; 
+               return;
        }
 
        localname = xmlSplitQName2((xmlChar *)qname, &prefix);
@@ -1704,13 +1724,17 @@ static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
        xmlChar           *contents = NULL;
        xmlNodePtr          node;
        int rv;
+       HashTable      *prop_hash;
 
        sxe = php_sxe_fetch_object(readobj TSRMLS_CC);
-       
+
        if (type == IS_BOOL) {
                node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
+               prop_hash = sxe_get_prop_hash(readobj, 1 TSRMLS_CC);
                INIT_PZVAL(writeobj);
-               ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(sxe_properties_get(readobj TSRMLS_CC)) > 0);
+               ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(prop_hash) > 0);
+               zend_hash_destroy(prop_hash);
+               efree(prop_hash);
                return SUCCESS;
        }
 
@@ -1755,7 +1779,7 @@ static int sxe_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
        sxe->iter.data = NULL;
 
        node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
-       
+
        while (node)
        {
                (*count)++;
@@ -1800,7 +1824,7 @@ static zend_object_handlers sxe_object_handlers = {
        sxe_property_delete,
        sxe_dimension_exists,
        sxe_dimension_delete,
-       sxe_properties_get,
+       sxe_get_properties,
        NULL, /* zend_get_std_object_handlers()->get_method,*/
        NULL, /* zend_get_std_object_handlers()->call_method,*/
        NULL, /* zend_get_std_object_handlers()->get_constructor, */
@@ -1808,7 +1832,8 @@ static zend_object_handlers sxe_object_handlers = {
        NULL, /* zend_get_std_object_handlers()->get_class_name,*/
        sxe_objects_compare,
        sxe_object_cast,
-       sxe_count_elements
+       sxe_count_elements,
+       sxe_get_debug_info
 };
 
 static zend_object_handlers sxe_ze1_object_handlers = {
@@ -1824,7 +1849,7 @@ static zend_object_handlers sxe_ze1_object_handlers = {
        sxe_property_delete,
        sxe_dimension_exists,
        sxe_dimension_delete,
-       sxe_properties_get,
+       sxe_get_properties,
        NULL, /* zend_get_std_object_handlers()->get_method,*/
        NULL, /* zend_get_std_object_handlers()->call_method,*/
        NULL, /* zend_get_std_object_handlers()->get_constructor, */
@@ -1832,7 +1857,8 @@ static zend_object_handlers sxe_ze1_object_handlers = {
        NULL, /* zend_get_std_object_handlers()->get_class_name,*/
        sxe_objects_compare,
        sxe_object_cast,
-       sxe_count_elements
+       sxe_count_elements,
+       sxe_get_debug_info
 };
 
 static zend_object_value sxe_object_ze1_clone(zval *zobject TSRMLS_DC)
@@ -2294,7 +2320,7 @@ void *simplexml_export_node(zval *object TSRMLS_DC)
 
        sxe = php_sxe_fetch_object(object TSRMLS_CC);
        GET_NODE(sxe, node);
-       return php_sxe_get_first_node(sxe, node TSRMLS_CC);     
+       return php_sxe_get_first_node(sxe, node TSRMLS_CC);
 }
 
 /* {{{ proto simplemxml_element simplexml_import_dom(domNode node [, string class_name])
index 63e57b38b0d1b13c87d1d1e1da8edbb0a23be7c2..f9a685663431b57ca744f082674fcfe0953a41f8 100644 (file)
@@ -98,6 +98,7 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC)
        char *class_name;
        zend_uint class_name_len;
        int (*php_element_dump_func)(zval**, int, va_list, zend_hash_key*);
+       int is_temp;
 
        if (level > 1) {
                php_printf("%*c", level - 1, ' ');
@@ -129,9 +130,10 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC)
                }
                php_printf("%sarray(%d) {\n", COMMON, zend_hash_num_elements(myht));
                php_element_dump_func = php_array_element_dump;
+               is_temp = 0;
                goto head_done;
        case IS_OBJECT:
-               myht = Z_OBJPROP_PP(struc);
+               myht = Z_OBJDEBUG_PP(struc, is_temp);
                if (myht && myht->nApplyCount > 1) {
                        PUTS("*RECURSION*\n");
                        return;
@@ -144,6 +146,10 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC)
 head_done:
                if (myht) {
                        zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_element_dump_func, 1, level);
+                       if (is_temp) {
+                               zend_hash_destroy(myht);
+                               efree(myht);
+                       }
                }
                if (level > 1) {
                        php_printf("%*c", level-1, ' ');