2

我不擅长 C 中的指针)

我的 PHP 扩展中的内存分配有问题。我正在尝试调用一个返回浮点数组的函数。

我用 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");
 }

完整代码

在这里我不需要mallocfree任何东西。(至少我不这么认为。在这个代码和函数的fortran版本中,我需要先allocate()fld。)

然而,在我的 PHP 扩展中,相同的代码返回了一个段错误。

当我在调用之前emallocefree(或只是mallocfree) fldc_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

根据this documentc_fstluk(buffer, key, &ni, &nj, &nk)将数据读入缓冲区,因此必须分配缓冲区(fld )。

在 C 版本中,如果fld未分配,如果通常不应该工作。但是根据您的系统等...或运气,fld *指针可能指向一个未写保护的随机空间(有效,但当然,这是非常危险的)。

因此,扩展还必须分配内存(永久或 PHP 请求寿命,仅取决于您的 ext)然后释放它 - 在您的情况下,它是临时分配,必须在离开 *php_function* 之前释放。

我可以在您提供的代码中看到,同时注释掉

  • 是否emalloc分配
  • 然后你强制模块返回0,因为你想测试这部分(而不是 PHP vars 创建等......)
  • 然后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 回答