3

In my Apache module, which is built in C++, I uses strings, vectors, and the related when attempting to provide functionality to my module.

My concern is that I am not using the Apache memory pool and that the program is going to segfault along the way, but at the same time I having difficulty with certain task such as this:

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++;
    }
}

which I am using a delimited string parser to parse URLs and domain names. Surely there is a more efficient way to provide this functionality. I am using the apr_table structure to contain each part, I know I could use an apr_array_header, but....

So I would like to know:

  1. Could I use Boost to provide the missing functionality SAFELY?
  2. Will I run into memory clashes because I am not using the pool memory?
  3. For string, vector, and etc that free their own memory, is this a problem laying in wait?

I did search for this issue, but the other issues do not seem to be the same.

4

2 回答 2

2

使用 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 容器的构造函数)。

于 2012-07-22T15:03:14.937 回答
0

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

于 2012-07-22T14:15:35.643 回答