我对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");
}
此处我没有malloc
或free
任何内容。 (至少我不这么认为。在这段代码和函数的fortran版本中,我需要首先allocate()
fld。)
然而,在我的PHP扩展中,相同的代码返回一个seg错误。
在调用emalloc
之前我efree
和malloc
(或只是free
和c_fstluk
)fld时,它可以正常工作,但我得到了大量的内存错误
[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 ===
(Full code with emalloc
commented out,line~398)
我打赌我在这里错过了一些简单的事情......
总而言之,在独立的C程序中,东西在没有任何分配的情况下工作。在PHP扩展中,它在我分配空间时起作用,但在抛出内存错误时,当我不分配空间时,它就会出错。
帮助?谢谢!
答案 0 :(得分:1)
根据此document,c_fstluk(buffer, key, &ni, &nj, &nk)
将数据读入缓冲区,因此必须分配缓冲区( fld )。
在C版本中,如果 fld 未分配通常不起作用。但是根据你的系统等......或者运气不错,fld *
指针可能指向一个没有写保护的随机空间(工作但当然这非常危险)。
因此扩展还要分配内存(永久或PHP请求 - 生命只取决于你的ext),然后释放它 - 在你的情况下它是一个临时分配,并且必须在离开* php_function之前释放*
我在您提供的代码中看到了什么,而注释掉了
emalloc
执行分配0
,因为你想测试这个部分(而不是PHP vars创建等......)efree
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)
(来源底部)