2016-09-09 7 views
0

私はPHP SAPIとZend Engineを試して、私が書いているアプリケーションにPHPを組み込みました。私は少しぶつかりました。私はPHPのinit関数内でグローバル変数を設定する際に問題を抱えていました。私は基本的なところに戻って、ZendのAPIの一例を取り上げました。Zend HashTable SIGSEGV

#include <php_embed.h> 
#include <zend_API.h> 
#include <zend.h> 
#include <zend_alloc.h> 
#include <zend_compile.h> 
#include <zend_hash.h> 
#include <zend_execute.h> 
#include <zend_globals_macros.h> 
#include <zend_ptr_stack.h> 
#include <zend_constants.h> 
#include <zend_extensions.h> 

static int php_ub_write(const char *str, unsigned int str_length TSRMLS_DC); 

static char *poutput = NULL; 
static int poutput_mal; 

static int register_globals(void) 
{ 
    zend_first_try { 

     HashTable *ht = NULL; 

     // allocate memory 
     //ht = emalloc(sizeof(HashTable)); 
     ALLOC_HASHTABLE(ht); 

     // initialize it internal state 

     zend_hash_init(ht, 50, NULL, ZVAL_PTR_DTOR, 0); 

     // destroy the hash table 

     zend_hash_destroy(ht); 

     // free the hash table itself 

     FREE_HASHTABLE(ht); 
    } zend_end_try(); 
} 

static void startup_php(void) 
{ 
    /* Create "dummy" argc/argv to hide the arguments 
    * meant for our actual application */ 

    int argc = 1; 
    char *argv[2] = { "cHTTPD", NULL }; 
    register_globals(); 
    php_embed_module.ub_write = php_ub_write; 
    php_embed_init(argc, argv);// PTSRMLS_CC); 
} 

static void shutdown_php(void) 
{ 
    php_embed_shutdown(TSRMLS_C); 
} 

static void execute_php(char *filename) 
{ 
    zend_first_try { 
     zend_file_handle script; 

     script.type = ZEND_HANDLE_FP; 
     script.filename = filename; 
     script.opened_path = NULL; 
     script.free_filename = 0; 

     if (!(script.handle.fp = fopen(script.filename, "rb"))) 
      return;// NULL; 

     php_execute_script(&script TSRMLS_CC); 
    } zend_end_try(); 
} 

int php(char *filename, char **string) { 
    startup_php(); 

    execute_php(filename); 

    *string = malloc(strlen(poutput) + 1); 
    strcpy(*string, poutput); 
    free(poutput); 

    shutdown_php(); 

    return 0; 
} 

static int php_ub_write(const char *str, unsigned int str_length TSRMLS_DC) 
{ 
    char *tmp; 

    if (poutput == NULL) 
    { 
     poutput = malloc(8000);//str_length + 1); 
     poutput_mal = 8000; 
     strncpy(poutput, str, str_length); 
    } 
    else 
    { 
     if ((strlen(poutput) + str_length) >= poutput_mal) 
     { 
      tmp = malloc(strlen(poutput)); 
      strncpy(tmp, poutput, strlen(poutput)); 

      poutput = malloc(strlen(poutput) + str_length + 1); 
      poutput_mal = strlen(poutput) + str_length + 1; 

      strncpy(poutput, tmp, strlen(tmp)); 

      free(tmp); 
     } 
     strncat(poutput, str, str_length); 

    } 

    return str_length; 
} 


int main() 
{ 
    char *string; 
    php("/home/durir/web/index.php", &string); 
} 

index.phpをコード:におけるemallocに戻ってそれをトレースコードの2行目(ALLOC_HASHTABLE)に

<?php 
echo "hello"; 
?> 

この依然としてSIGSEGVs。何か案は?私は完全に困惑している。

+0

'ALLOC_HASHTABLE'マクロ/関数の詳細がなくても、あなたに伝えることはあまりありません。あなたは[mcve]の方向に長い道のりを歩んできましたが、あなたはまだそこにいません。 –

+0

野生の推測: 'ALLOC_HASHTABLE()'には、割り振りと再割り振りの両方を行うための条件付きコードがあります。どちらが必要なのかを区別するために、引数がNULLかどうかをテストします。その場合、 'ht'を' NULL'に初期化したいとします。 –

答えて

0

PHPソースを調べると、マクロが展開され、zend_alloc.cのコードが実行されることがわかります。それは独自のメモリマネージャを使用しており、zendメモリマネージャが初期化される前にそれを呼び出すことになります。予想(MacOSの10.12.1シエラ上でテスト)として

static int register_globals() { 
    zend_first_try { 
     start_memory_manager(); 
     HashTable *ht; 
     ALLOC_HASHTABLE(ht); 
     zend_hash_init(ht, 50, NULL, ZVAL_PTR_DTOR, 0); 
     zend_hash_destroy(ht); 
     FREE_HASHTABLE(ht); 
     return SUCCESS; 
    } zend_end_try(); 
    return FAILURE; 
} 

これを実行した後、あなたのコードは動作します。これを修正するには、単にstart_memory_manager();ALLOC_HASHTABLE(ht);前に挿入します。

編集:

は実際には、より良いカプセル化のために、あなたはおそらくregister_globals()startup_php()register_globals();start_memory_manager();を入れてはいけません。