代码之家  ›  专栏  ›  技术社区  ›  Ad N

在PHP扩展中,推荐从值返回STD::字符串的方法

  •  2
  • Ad N  · 技术社区  · 8 年前

    我们有一个简单的PHP函数,它的目的是调用C++自由函数 std::string callLibrary(std::string) 并返回 std::string 返回值。

    目前看来:

    PHP_FUNCTION(call_library)
    {
        char *arg = NULL;
        size_t arg_len, len;
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE)
        {
            return;
        }
    
        // Call underlying library
        std::string callResult = callLibrary(arg);
        zend_string * result = zend_string_init(callResult.c_str(), callResult.size(), 0);
        RETURN_STR(result);
    }
    

    我们找不到描述 zend_string_init RETURN_STR() 最接近的是: http://www.phpinternalsbook.com/php7/internal_types/strings/zend_strings.html

    特别是,它为 Zend_字符串初始化

    如果传递0,则要求引擎使用请求绑定堆 使用Zend内存管理器进行分配。这样的分配将 在当前请求结束时销毁。如果你不这样做 你自己,在一个调试版本中,引擎会对你大喊大叫 您刚刚创建的内存泄漏。如果你通过了1,你就要求我们 称为__persistent_分配,即引擎将使用 传统的c malloc()调用,不会跟踪内存分配 无论如何。

    看来我们想要 0 价值,但确实如此 返回\u str() 然后释放分配的内存?(文本有点含糊不清,但似乎破坏应该是明确的) 有没有更惯用的方法 STD::字符串 来自php扩展函数的值?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Roger Gee    8 年前

    为了回答您的问题,我将讨论一点PHP内存分配,然后讨论您的特定问题。

    关于PHP内存分配

    编写PHP扩展时,可以执行两种内存分配:

    • 跟踪内存分配
    • 持久内存分配

    跟踪内存分配是一种优化,允许PHP引擎对原始内存分配有更多的控制。zend内存管理器(zendmm)充当标准内存分配库之上的包装器。这个内存管理器允许PHP通过清除请求结束时没有显式释放的任何跟踪内存来避免内存泄漏。此外,这允许引擎设定内存限制(例如 php.ini 设置 memory_limit )跟踪内存也称为 按请求 因为这些原因记忆。

    持久内存分配是由C库管理的标准内存分配(例如 malloc 和朋友)。值得注意的是,在C++中, new delete 通常呼叫到 马洛克 free 分别。在PHP中,持久性内存分配在处理请求时仍然有效,并且它可能存在以服务多个请求。因此,使用这些类型的分配可能导致内存泄漏。

    在PHP API中,有一些宏是为执行跟踪或持久内存分配而定义的。例如, emalloc efree 类似于 马洛克 自由的 用于跟踪(即每个请求)内存管理。宏 pemalloc pefree 用于跟踪或持久分配,具有要切换的参数。例如, pemalloc(32,1) 分配32个持久字节的块,而 pemalloc(32,0) 等于 emalloc(32) 它分配32个跟踪字节的块。

    除了原始内存分配函数之外,PHP API还提供对由更高级别函数启动的内存分配的控制。例如,创建php7 zend_string 结构 zend_string_init 允许您通过第三个参数选择所需的内存分配类型。这遵循了整个API中的一个常见习惯用法, 0 指示跟踪分配和 1 表示持久分配。

    关于 Zend_字符串 , Zend_字符串初始化 RETURN_STR

    我对php7的熟悉程度不如对php5的熟悉程度,但是很多概念都被继承了,我认为我已经阅读了足够的源代码来回答这个问题。当您分配 Zend_字符串 到A zval 使用 返回\u str , the 泽瓦尔 负责释放 Zend_字符串 (在php5中,这只是一个 char* 但概念是一样的)。Zend引擎希望使用跟踪内存管理器来分配大多数(如果不是所有)对象。在php5语言中,分配给 泽瓦尔 必须已通过分配 电子合金 因为代码总是调用 自由的 在字符串缓冲区上 泽瓦尔 被摧毁。在PHP7中似乎有 an exception 自从 Zend_字符串 结构可以记住使用了哪种分配类型。不管怎样,最好的做法是始终将跟踪分配用作默认分配,除非您有充分的理由这样做。因此,您当前的代码看起来很好,因为它通过了 作为第三个参数 Zend_字符串初始化 .

    破坏 Zend_字符串 不应在代码中显式,因为 泽瓦尔 稍后再处理。另外,该进程取决于用户空间如何对返回的 泽瓦尔 . 这不是你要担心的事。