Hi,
It seems something has changed recently regarding referencing
constants that has broken my extension and I'm trying to figure out
exactly what the right thing to do is.
When passing a string constant to an extension function, within the
extension I have been saving that string directly for possible
retrieval later (see code below).
This has worked fine but it seems with recent releases of PHP (5.2.5
is what I'm testing with) the memory the string points to gets
clobbered after the function returns. Meaning when I retrieve the
value later it is garbage data.
I suppose thinking a string parameter would be valid after the call
was a bold assumption but it worked.
Has something changed regarding parameters that are constants?
Or was my code always broken and it's just a coincidence that I'm
seeing corrupted values now?
How can I convert a string constant to a value that I can save internally?
Must I simply copy the string always?
Does zend_get_constant help?
Mike
PHP_FUNCTION(foo_status)
{
zval *r;
char *s = "";
int slen;
struct foo *foo = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|s!",
&r, &s, &slen) == FAILURE) {
RETURN_FALSE;
}
if (r)
foo = (struct foo *)zend_fetch_resource(&r TSRMLS_CC,
-1, "foo", NULL, 1, le_foo);
if (ZEND_NUM_ARGS() > 1) {
foo_status(foo) = s; // save the status for possible retrieval later
}
RETURN_STRING(foo_status(foo), 1);
}
This has worked fine
Are you really sure?
Does valgrind confirm it?
PHP_FUNCTION(foo_status)
{
zval *r;
char *s = "";
int slen;
struct foo *foo = NULL;if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|s!", &r, &s, &slen) == FAILURE) { RETURN_FALSE; } if (r) foo = (struct foo *)zend_fetch_resource(&r TSRMLS_CC, -1, "foo", NULL, 1, le_foo); if (ZEND_NUM_ARGS() > 1) { foo_status(foo) = s; // save the status for possible retrieval later }
I don't know what "foo_status(foo)" is supposed to mean here,
but this code was never supposed to work.
You have to copy the string if you want to store it.
--
Wbr,
Antony Dovgal
This has worked fine
Are you really sure?
It has worked just fine under load in production with PHP 5, 5.0 and
5.1. It seems there's something different about 5.2.
Does valgrind confirm it?
I have run valgrind (primarily for leak checking) and I don't recall
seeing any complaints about the code or objects in question.
PHP_FUNCTION(foo_status)
{
zval *r;
char *s = "";
int slen;
struct foo *foo = NULL;if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|s!", &r, &s, &slen) == FAILURE) { RETURN_FALSE; } if (r) foo = (struct foo *)zend_fetch_resource(&r TSRMLS_CC, -1, "foo", NULL, 1, le_foo); if (ZEND_NUM_ARGS() > 1) { foo_status(foo) = s; // save the status for possible retrieval later }
I don't know what "foo_status(foo)" is supposed to mean here,
It's saving s into foo. It's actually an errno style macro that
dereferences a char ** to assign the value to a member of foo.
but this code was never supposed to work.
Well it did.
You have to copy the string if you want to store it.
Ok. Doesn't look like I have much choice. I just wanted to understand
the problem better. I'll just copy the strings.
But it does seem odd to me that PHP does not always reference string
constants directly. I mean, why copy if you don't have to?
Mike
You have to copy the string if you want to store it.
Ok. Doesn't look like I have much choice. I just wanted to understand
the problem better. I'll just copy the strings.But it does seem odd to me that PHP does not always reference string
constants directly. I mean, why copy if you don't have to?
Because you have to copy something that is going to be freed by PHP.
That's how it works & worked for ages - you don't have to free the
strings you get from zend_parse_parameters() because PHP does it for you.
--
Wbr,
Antony Dovgal
You have to copy the string if you want to store it.
Ok. Doesn't look like I have much choice. I just wanted to understand
the problem better. I'll just copy the strings.But it does seem odd to me that PHP does not always reference string
constants directly. I mean, why copy if you don't have to?Because you have to copy something that is going to be freed by PHP.
That's how it works & worked for ages - you don't have to free the
strings you get from zend_parse_parameters() because PHP does it for you.
I newer versions of zend engine are more aggressive about collecting
that memory and now it's caught up with me.
I have changed my code to make a copy and all seems to be working well again.
Thanks,
Mike
--
Michael B Allen
PHP Active Directory SPNEGO SSO
http://www.ioplex.com/
Because you have to copy something that is going to be freed by PHP.
That's how it works & worked for ages - you don't have to free the
strings you get from zend_parse_parameters() because PHP does it for you.I newer versions of zend engine are more aggressive about collecting
that memory and now it's caught up with me.
No, it always worked this way.
--
Wbr,
Antony Dovgal
You have to copy the string if you want to store it.
Ok. Doesn't look like I have much choice. I just wanted to
understand
the problem better. I'll just copy the strings.But it does seem odd to me that PHP does not always reference string
constants directly. I mean, why copy if you don't have to?Because you have to copy something that is going to be freed by PHP.
That's how it works & worked for ages - you don't have to free the
strings you get from zend_parse_parameters() because PHP does it for
you.
Or, to put it another way, as I understand it:
You know that 0|1 flag you can use when you return a value?
That flag isn't about whether or not PHP will nuke the value when it
exits; PHP is GOING to nuke that value.
The flag is about whether PHP should copy it for you, so it can nuke
its own copy, or if you've already made it a PHP value/copy, which PHP
can safely nuke.
--
Some people have a "gift" link here.
Know what I want?
I want you to buy a CD from some indie artist.
http://cdbaby.com/from/lynch
Yeah, I get a buck. So?