Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:73492 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 75121 invoked from network); 31 Mar 2014 13:01:53 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 31 Mar 2014 13:01:53 -0000 Authentication-Results: pb1.pair.com smtp.mail=johannes@schlueters.de; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=johannes@schlueters.de; sender-id=unknown Received-SPF: error (pb1.pair.com: domain schlueters.de from 217.114.215.10 cause and error) X-PHP-List-Original-Sender: johannes@schlueters.de X-Host-Fingerprint: 217.114.215.10 mail.experimentalworks.net Received: from [217.114.215.10] ([217.114.215.10:59358] helo=mail.experimentalworks.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 9A/54-44499-14769335 for ; Mon, 31 Mar 2014 08:01:53 -0500 Received: from [192.168.2.31] (ppp-188-174-47-142.dynamic.mnet-online.de [188.174.47.142]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: johannes@schlueters.de) by mail.experimentalworks.net (Postfix) with ESMTPSA id 504CA46529; Mon, 31 Mar 2014 15:02:38 +0200 (CEST) To: Kajetan Dolinar Cc: internals@lists.php.net In-Reply-To: <7a275f0b0f3d960c343fa59524129e0b@jesej.si> References: <61554d9f645998b2d0498ccd7da6f9e8@jesej.si> <1396262306.2982.73.camel@guybrush> <7a275f0b0f3d960c343fa59524129e0b@jesej.si> Content-Type: text/plain; charset="UTF-8" Date: Mon, 31 Mar 2014 15:01:22 +0200 Message-ID: <1396270882.2982.98.camel@guybrush> Mime-Version: 1.0 X-Mailer: Evolution 2.30.3 Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Fwd: zend_std_get_method : Address 0xffffffff is not stack'd, malloc'd or (recently) free'd From: johannes@schlueters.de (Johannes =?ISO-8859-1?Q?Schl=FCter?=) On Mon, 2014-03-31 at 14:09 +0200, Kajetan Dolinar wrote: > Johaness, thank you for your attention ... > > >> The reason most probably lies within my code, but I don't have enough > >> PHP Zend engine > >> hacking experience to get to it by myself - it's my first PHP > >> extension. Much obliged > >> for intuitions from experienced for what could bring about such kind > >> of fault. > > > > Reduce you ode till it works or share more details .. > Yes, that may now be the only possible way to procede. Well, you could also provide the PHP version number you are using ... maybe an experienced developer might then point you in the right direction. I simply have no clue which exact line zend_object_handlers.c:847 is. So which structure is being read. Maybe it also helps to use --db-attach=yes for valgrind to inspect the state ... the only information the given valgrind output gives is that something weird is happening while trying to call a method on an object. Best, of course, would be to show code. (Mind: It is legal to have an open source extension on top a closed library if you don't want to share some library ... benefit then is that it might be put in PECL, eventually you get windows builds and bugfixes from PHP maintainers aside from improved visibility to potential users ...) > > Depends on what you want to use that memory for and what you optimize > > for. i.e. if you want to stick data in PHP data structures it should be > > emalloc'd with one block per item so PHP an free it. > > I would like to see from the address value itself whether that address > was produced by e{m|re}alloc() so that I have to efree() it, or by > pe{m|re}alloc() that I have to pefree(), or whether it falls within > some other data segment such as static data which I should not > free() in any way. For example: > > struct record { > int id; > char * name; > . . . > }; > > . . . > > struct record * a = emalloc(sizeof(struct record)); > a->id = 1; a->name = estrdup("name1"); > > struct record * b = emalloc(sizeof(struct record)); > b->id = 2; b->name = "name2"; > > Clearly, there should be efree(a->name) as well as efree(a). However, > in case of b, only efree(b) is appropriate whereas efree(b->name) > would produce an error. > How can I find out whether an address belongs to efree() or to > pefree() or to none of that? The typical pattern we use is either to add a flag to the structure, something like struct record { int id; zend_bool need_free; /* zend_bool is a uint */ char * name; . . . }; this obviously increases memory usage by sizeof(zend_bool) [+alignment] for ach element and requires more care when creating/copying these structures. Some prefer doing this with struct record { int id; void * to_free; /* equal to name if needs to be free'd, else NULL */ char * name; . . . }; The other approach is to enforce ownership inside the structure, thus requiring more copies but it ensures that ownership is fully clear and prevents double frees which might occur with your approach if a record is copied but one doesn't copy the name. This trades some CPU and memory for safety which in most cases is preferred. johannes