【问题标题】:Can I use Boost and/or C++ libraries SAFELY inside an Apache module?我可以在 Apache 模块中安全地使用 Boost 和/或 C++ 库吗?
【发布时间】:2012-07-22 13:38:41
【问题描述】:

在我用 C++ 构建的 Apache 模块中,我在尝试为我的模块提供功能时使用字符串、向量和相关内容。

我担心的是我没有使用 Apache 内存池,并且程序在此过程中会出现段错误,但同时我在执行某些任务时遇到了困难,例如:

static void parseSTR(char *input, const char *sep, int &count, apr_table_t *&values, apr_pool_t *mp)
{
    char *part, *next;

    if (isStrNull(input)) 
        return;

    count = 1;

    part = apr_strtok(input, sep, &next);

    while (part) {
        apr_table_set(values, apr_itoa(mp, count), part);

        part = apr_strtok(NULL, sep, &next);

        count++;
    }
}

我正在使用分隔字符串解析器来解析 URL 和域名。当然,有一种更有效的方法来提供此功能。我正在使用 apr_table 结构来包含每个部分,我知道我可以使用 apr_array_header,但是....

所以我想知道:

  1. 我可以使用 Boost 安全地提供缺失的功能吗?
  2. 我会因为没有使用池内存而遇到内存冲突吗?
  3. 对于释放自己内存的字符串、向量等,这是一个等待的问题吗?

我确实搜索过这个问题,但其他问题似乎不一样。

【问题讨论】:

    标签: c++ apache boost apache-modules


    【解决方案1】:

    使用 Boost 应该是安全的,这取决于您使用的具体部分,但要对其安全性做出任何明确的调用。

    至于内存管理,您可以编写自己的 std::allocator 实现,使用 Apache/APR 的内存分配。然后,您可以将此分配器作为模板参数传递给您正在使用的 STL 容器(通常是第二个模板参数)。

    至于 Boost 的智能指针(如果您正在使用它们),它们可以(在构造时)被赋予一个函数指针作为实现内存释放的参数(作为 delete 的替代品)。

    例如像这样的分配器可以为您解决问题:

    #include <stdexcept>
    
    template <typename T>
    class apr_allocator
    {
        public:
            typedef size_t    size_type;
            typedef ptrdiff_t difference_type;
            typedef T*        pointer;
            typedef const T*  const_pointer;
            typedef T&        reference;
            typedef const T&  const_reference;
            typedef T         value_type;
    
            template<typename U>
            struct rebind
            { typedef apr_allocator<U> other; };
    
            pointer allocate(size_type n, const void* = 0)
            {
                pointer new_mem = apr_do_whatever_is_necessary_to_allocate(n * sizeof(value_type));
                if (!new_mem)
                    throw std::bad_alloc();
                return new_mem;
            }
    
            void deallocate(pointer p, size_type n)
            {
                apr_release_memory(p, n);
            }
    
            pointer address(reference r) const
            {
                return &r;
            }
    
            const_pointer address(const_reference r) const
            {
                return &r;
            }
    
            size_type max_size() const
            {
                // Largest amount of elements T that can meaningfully be allocated
                return 1337;
            }
    
            void construct(pointer p, const_reference val)
            {
                new ((void *)p) value_type(val);
            }
    
            void destroy(pointer p)
            {
                p->~T();
            }
    };
    
    template <typename T>
    inline bool operator==(const apr_allocator<T>& a, const new_allocator<T>& b)
    {
        if (&a == &b)
            return true;
        if (/* a can deallocate elements created with b and vice-versa */)
            return true;
        return false;
    }
    
    template <typename T>
    inline bool operator!=(const apr_allocator<T>& a, const apr_allocator<T>& b)
    {
        return !(a == b);
    }
    

    还要注意,如果您的分配器需要内部状态(例如,对特定内存池的引用),您必须确保分配器是可复制构造的。此外,它必须是默认可构造的(尽管您可以将预先构造的实例作为参数传递给 STL 容器的构造函数)。

    【讨论】:

      【解决方案2】:

      我们在 Windows 上的 Apache 中大量使用 C++ 和 Boost,我们没有发现与使用 new 或类似 C++isms 相关的任何问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-20
        • 1970-01-01
        • 2011-04-23
        • 2019-08-13
        • 2011-10-14
        • 2020-12-10
        • 2012-11-30
        • 1970-01-01
        相关资源
        最近更新 更多