PHP内核pemalloc的persistent硬编码为1,我们该如何去进行释放
举个例子,在PHP
内核初始化interned string
的时候,PHP
内核使用的是pemalloc
,并且persistent
设置为了1
:
1 2 3 4 5 6 7 8 9 10
| ZEND_API void zend_interned_strings_init(void) { zend_known_strings = pemalloc(sizeof(zend_string*) * ((sizeof(known_strings) / sizeof(known_strings[0]) - 1)), 1); for (i = 0; i < (sizeof(known_strings) / sizeof(known_strings[0])) - 1; i++) { str = zend_string_init(known_strings[i], strlen(known_strings[i]), 1); zend_known_strings[i] = zend_new_interned_string_permanent(str); } }
|
我们看到zend_known_strings
这个地方是通过pemalloc
来分配内存的,并且persistent
设置为1
了。但是释放的时候,我们发现用的是free
,而不是pefree
:
1 2 3 4 5 6 7
| ZEND_API void zend_interned_strings_dtor(void) { zend_hash_destroy(&interned_strings_permanent);
free(zend_known_strings); zend_known_strings = NULL; }
|
实际上,当persistent
为1
的时候,pemalloc
就是malloc
。所以,这里可以用free
来进行释放。但是,当时我觉得,为了对应pemalloc
,释放的时候用pefree
会更好一点。于是我改成了pefree(zend_known_strings, 1)
,但是,nikic
给我的解释如下:
1 2 3
| 通常,只有在动态传递persistent时才使用pefree()。
我们有时使用pemalloc(x, 1)和硬编码的persistent=1,但这是有原因的:pemalloc(x, 1)是一个“可靠的分配器”,永远不会返回NULL。因此,它与malloc(x)不同。
|
我们可以看一下pemalloc
会做什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #define pemalloc(size, persistent) ((persistent)?__zend_malloc(size):emalloc(size))
ZEND_API void * __zend_malloc(size_t len) { void *tmp = malloc(len); if (EXPECTED(tmp || !len)) { return tmp; } zend_out_of_memory(); }
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void) { fprintf(stderr, "Out of memory\n"); exit(1); }
|
所以,当pemalloc
的persistent
为1
的时候,实际上还是调用的malloc
,但是会去判断是否成功的分配到了内存,如果没有分配到内存,直接退出进程。所以,我们可以认为,pemalloc
的返回值一定不是NULL
,如果是NULL
,直接退出进程。
所以,我们可以得出一个结论,如果我们确定了内存一定是通过malloc
分配的,那么,我们可以直接使用free
来释放内存(用不用pefree
都无所谓了);但是如果不能够确定是不是malloc
来分配的,那么,我们应该使用pefree
来释放内存(此时persistent
应该是一个变量,而不是硬编码)