Making a variable global question

php.internals

Unnamed Person

23 years ago
I am trying to make a function for my extension that makes a predefined variable global I have tried something along the lines of: if(zend_hash_find(&EG(symbol_table), var, strlen(var)+1, (void **) &vars_data)!=FAILURE) { ZEND_SET_SYMBOL(EG(active_symbol_table), var, *vars_data); } but it seg faults upon second execution. Can someone reccomend a more successful method of accomplishing this? Chhers, Ken

Mark Spruiell

23 years ago
Hi Ken, I'm fairly new to PHP extension programming, so forgive me if I'm missing the obvious, but your code appears to be trying to copy a global variable to a local scope. Is that your intent? If so, why can't the script do this itself by using a "global" declaration for the variable? For example: <? $v = "foo"; function bar() { global $v; echo "v = $v\n"; } ?> As for why you're getting a segfault, I suspect it's a reference counting issue. Have a look at the definition of ZEND_SET_SYMBOL_WITH_LENGTH in zend_API.h and you'll see it is modifying the container you retrieved from EG(symbol_table). Good luck, - Mark

Unnamed Person

23 years ago
On Fri, 1 Aug 2003, Mark Spruiell wrote: Mark, thanks for your reply. The situation is, is that I am writing a large piece of software with several hundred functions. At the beginning of each function I have som initialization code that allows me to do several thing. Parse through the variables in a non standard way, and define a few variables to be global within the function. The only way I was able to accomplish this in the past was to call an include from the beginning of each function (as there is no way to write a function that uses func_get_args()). Calling this include however is quite inneficient, and I have replaced most of what it does with my C extension. I have also tried using the zend_register_auto_global function, but this appears to cause a great deal of unpredictable behaviour. Cheers, Ken

Rasmus Lerdorf

23 years ago
Your code doesn't make much sense to me. This is your code, right? if(zend_hash_find(&EG(symbol_table), var, strlen(var)+1, (void **)&vars_data)!=FAILURE) { ZEND_SET_SYMBOL(EG(active_symbol_table), var, *vars_data); } So you look for a global variable named whatever the contents of 'var' is. If you find it, you put it in the function-local symbol table. This is not at all what you said you wanted to do. And you don't check to see if the active_symbol_table is the same as the symbol_table which it would be if you were to call this function from the global scope. -Rasmus On Fri, 1 Aug 2003, Ken Spencer wrote:

Unnamed Person

23 years ago
On Fri, 1 Aug 2003, Rasmus Lerdorf wrote: My apologies, my explanation wasn't very clear. my initialization function needs to both parse the argument stack, but it also declars a few user defined variables to be global. I did not include the portion of code in my snippet that ensures the function is only called from within a user defined function. Ken

Zeev Suraski

23 years ago
At 03:44 01/08/2003, Ken Spencer wrote:
>I am trying to make a function for my extension that makes a predefined >variable global > >I have tried something along the lines of: > > if(zend_hash_find(&EG(symbol_table), var, strlen(var)+1, (void **) > &vars_data)!=FAILURE) >{ > ZEND_SET_SYMBOL(EG(active_symbol_table), var, *vars_data); >}
You're messing with the reference count here. ZEND_SET_SYMBOL() 'takes over' this zval, and the original copy becomes corrupted. That's probably why it fails the second time you try it. You need to use ZEND_SET_SYMBOL_WITH_LENGTH() instead, and take care of the reference count manually. When touching a zval coming back from an engine-controlled symbol table, you must take care of the reference count (in this case, increment it). If you want the two variables to be references, that is, changing one would change the other - you should also turn on the is_ref bit, and not forget to first separate it. It should look something like this: if(zend_hash_find(&EG(symbol_table), var, strlen(var)+1, (void **) &vars_data)!=FAILURE) { SEPARATE_ZVAL_IF_NOT_REF(vars_data); (*vars_data)->refcount++; ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), var, strlen(var)+1, *vars_data, (*vars_data)->refcount, 1); } Zeev