Help, please! The Zend API is driving me mad!!!

php.internals

Oriol

23 years ago
Aaaaaaaaaaargh! When I run the following code... ---------------------------------------------- char fname[256]; zval **retval; zval *zfname; strcpy(fname, "rand"); zend_printf("Step 1...\n"); MAKE_STD_ZVAL(zfname); zend_printf("Step 2...\n"); ZVAL_STRING(zfname, fname, 1); zend_printf("Step 3...\n"); TSRMLS_FETCH(); zend_printf("Step 4...\n"); if (call_user_function_ex(CG(function_table), NULL, zfname, retval, 0, NULL, 0, NULL TSRMLS_DC) == SUCCESS) { zend_printf("The function has ben called.\n"); } ----------------------------------------------- ... i get: Step 1... Step 2... Step 3... Step 4... Segmentation fault Could someone tell me what I'm doing wrong? Thank you very much, Oriol

Joao Prado Maia

23 years ago
My code is just as bad, but I remember that it used to work: PHP_FUNCTION(jtemplate_set_root) { zval **z_root_dir; char *root_dir = NULL; int argc = ZEND_NUM_ARGS(); zval func; zval *retval = NULL; zval *args[1]; if (argc < 0 || argc > 1 || zend_get_parameters_ex(argc, &z_root_dir) == FAILURE) { WRONG_PARAM_COUNT; } if (argc > 0) { convert_to_string_ex(z_root_dir); root_dir = estrndup(Z_STRVAL_PP(z_root_dir), Z_STRLEN_PP(z_root_dir)); } else { root_dir = estrndup(".", sizeof(".") - 1); } INIT_ZVAL(func); ZVAL_STRING(&func, "is_dir", 1); MAKE_STD_ZVAL(args[0]); ZVAL_STRING(args[0], root_dir, 1); MAKE_STD_ZVAL(retval); /* check to see if the directory really exists and that is a real directory */ if (call_user_function(EG(function_table), NULL, &func, retval, 1, args TSRMLS_CC) == FAILURE) { zend_error(E_ERROR, "%s(): could not call is_dir().", get_active_function_name(TSRMLS_C)); } if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) { ZVAL_STRING(&func, "halt", 1); ZVAL_STRING(args[0], "no such directory", 1); call_user_function(NULL, &getThis(), &func, retval, 1, args TSRMLS_CC); zval_dtor(&func); } efree(root_dir); zval_dtor(retval); zval_ptr_dtor(&args[0]); add_property_stringl(getThis(), "root", Z_STRVAL_PP(z_root_dir), Z_STRLEN_PP(z_root_dir), 1); ZEND_PUTS(get_active_function_name(TSRMLS_C)); RETURN_TRUE; } Yes, this _is_ nasty ;) Cheers, Joao

Sara Golemon

23 years ago
I see two notable problems, though there may be more: 1) TSRMLS_DC should be TSRMLS_CC _DC is only used for function declarations, _CC is used for passing the tsrm parameter to it. (Did you configure with --enable-maintainer-zts [ or --enable-experimental-zts if this is PHP4 ]? ) 2) You need to either allocate the zval* for retval or (better) define retval as a zval* (not zval**) and pass it as &retval. The way you have it now will have call_user_func attempt to overwrite the data at the address pointed to by retval (which at the moment is undefined). This is probably what is specifically causing your segfault here. -Sara "Oriol" <omagrane@anthill.es> wrote in message news:000701c334ed$9850c6f0$0601a8c0@pii...

(Marcus Börger)

23 years ago
Hello Oriol, Tuesday, June 17, 2003, 6:29:14 PM, you wrote: O> Aaaaaaaaaaargh! O> When I run the following code... O> ---------------------------------------------- O> char fname[256]; O> zval **retval; O> zval *zfname; O> strcpy(fname, "rand"); O> zend_printf("Step 1...\n"); O> MAKE_STD_ZVAL(zfname); O> zend_printf("Step 2...\n"); O> ZVAL_STRING(zfname, fname, 1); O> zend_printf("Step 3...\n"); O> TSRMLS_FETCH(); O> zend_printf("Step 4...\n"); O> if (call_user_function_ex(CG(function_table), NULL, O> zfname, retval, 0, NULL, 0, O> NULL TSRMLS_DC) == SUCCESS) O> { O> zend_printf("The function has ben called.\n"); O> } O> ----------------------------------------------- O> ... i get: O> Step 1... O> Step 2... O> Step 3... O> Step 4... O> Segmentation fault O> Could someone tell me what I'm doing wrong? O> Thank you very much, - The line TSRMLS_FETCH() must be the last line after all local variable declarations. - TSRMLS_DC must be replaced with TSRMLS_CC in the call_user_function_ex() call. - CG means Compiler Globals so i guess you want the corresponging Executor Global_ EG(function_table) - If the third parameter to ZVAL_STRING() is a non zero value the string value is copied to the zval. Since it must be freeable by the zval destructor it must be a value stroed in memory allocated by emalloc(). Where this happens doesn't matter so the following is enough: ZVAL_STRING(zfname, "rand", 1);
-- Best regards, Marcus mailto:helly@php.net