2

私はCのポインタが苦手です)

PHP拡張機能のメモリ割り当てに問題があります。floatの配列を返す関数を呼び出そうとしています。

私はCで小さなテストスクリプトを書きました、そしてそれは動作します。

基本的には、

float *fld;
...
ier = c_fstluk(fld, key, &ni, &nj, &nk);
...
// Read the array as a 2d field
for (i=0; i<ni; i++) {
   for (j=0; j<nj; j++) {
      // Values come transposed..
      printf("%15.6E", *(fld+(ni*j)+i));
      if (j<nj-1) printf(", ");
   }
   printf("\n");
 }

完全なコード

mallocここでは何もする必要はありませんfree。(少なくとも私はそうは思いません。このコードと関数のFortranバージョンでは、allocate()最初にfldする必要があります。)

しかし、私のPHP拡張機能では、同じコードがセグメンテーション違反を返します。

を呼び出す前に私emallocefree(またはちょうどmallocと)fldを実行すると、動作しますが、大量のメモリエラーが発生します。freec_fstluk

[Wed Jan  9 15:34:33 2013]  Script:  '/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php'
/Users/matt/aurams/trunk/web/php/php-src/Zend/zend_API.c(1295) :  Freeing 0x10D953060 (72 bytes), script=/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php
/Users/matt/aurams/trunk/web/php/php-src/Zend/zend_hash.c(412) : Actual location (location was relayed)
Last leak repeated 779 times
[Wed Jan  9 15:34:33 2013]  Script:  '/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php'
/Users/matt/aurams/trunk/web/php/php-src/Zend/zend_API.c(1292) :  Freeing 0x10D9531A0 (32 bytes), script=/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php
Last leak repeated 779 times
[Wed Jan  9 15:34:33 2013]  Script:  '/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php'
ext/fstd/fstd.c(414) :  Freeing 0x10D9538D0 (72 bytes), script=/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php
/Users/matt/aurams/trunk/web/php/php-src/Zend/zend_API.c(982) : Actual location (location was relayed)
Last leak repeated 29 times
[Wed Jan  9 15:34:33 2013]  Script:  '/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php'
/Users/matt/aurams/trunk/web/php/php-src/Zend/zend_hash.c(450) :  Freeing 0x10D954C08 (256 bytes), script=/Users/matt/aurams/trunk/web/php/php-src/ext/fstd/fstd.php
Last leak repeated 29 times
=== Total 1620 memory leaks detected ===

コメントアウトされた完全なコードemalloc、行〜398)

私はここで簡単な何かが欠けているに違いない。

要約すると、スタンドアロンのCプログラムでは、割り当てなしで機能します。PHP拡張機能では、スペースを割り当てると機能しますが、メモリエラーが発生します。スペースを割り当てないと、セグメンテーション違反が発生します。

ヘルプ?ありがとう!

4

1 に答える 1

1

このドキュメントによると、はc_fstluk(buffer, key, &ni, &nj, &nk)データをバッファに読み込むため、バッファ(fld)を割り当てる必要があります。

Cバージョンでは、 fldが割り当てられていない場合、通常は機能しないはずです。ただし、システムなどによっては、または運によっては、fld *ポインタが書き込み保護されていないランダムなスペースを指している場合があります(機能しますが、もちろん、これは非常に危険です)。

したがって、拡張機能はメモリ(永続的またはPHPリクエストライフのいずれか-extに応じてのみ)を割り当ててから解放する必要があります-あなたの場合は一時的な割り当てであり、*php_function*を離れる前に解放する必要があります。

コメントアウトしている間、あなたが提供したコードで私が見ることができるもの

  • emalloc割り当てを行います
  • 0次に、この部分をテストしたいので、モジュールを強制的に戻します(PHP変数の作成などではありません...)
  • その後、あなたはefree fld
  • したがって、fldは解放されず、メモリリークが発生します

したがって、これはおそらく単純な間違いefreeです。関数が戻る直前に移動する必要があります。

fld = emalloc(ni*nj*sizeof(float*)); /* sizeof(float)  INSTEAD? */

// Read the field pointed by the given key
ier = c_fstluk(fld, key, &ni, &nj, &nk);

/* ... */

php_printf("\nDone.\n");

efree(fld);

RETURN_LONG(0);

コメントに基づいて編集

  • (float *)割り当てがに変更されました(float)
  • ALLOC_INIT_ZVAL(arow)すべての反復で実行する必要があります(ソース下部)
于 2013-01-10T17:12:37.263 に答える