0

I have some code that contains a self-made hashtable using calloc and malloc for memory allocation. I would like to modify these parts using a shared_ptr with a custom deleter that frees automatically the allocated memory. The code is part of the mmseg chinese segmenter algorithm, it is working great but is such a mess as it leaves memory leaks. I am considering to rewrite that code using a unordered_map or such, but for now I would like to make these changes.

I read the answers on similar questions, such as shared_ptr with malloc and free or Accessing calloc'd data through a shared_ptr, but I have problems to use that on the code below.

I have these lines where I am not able to wrap the calls with the smart pointer. So maybe somebody can help me out with this:

struct Word {
    unsigned char nbytes;   /* number of bytes */
    char length;   /* number of characters */
    unsigned short freq;
    char text[word_embed_len];
};

struct Entry {
    Word *word;
    Entry *next;
};

static Entry **new_bins = static_cast<Entry **>(std::calloc(init_size, 
    sizeof(Entry *)));
Entry *entry, ...;
...
new_bins[hash_val] = entry;
....
free(new_bins);

The above calloc call I would feed shared pointer with the result of calloc, such as

std::shared_ptr<Entry *> binsPtr(new_bins, freePtr());

I am not shure if this is correct.

mmseg uses a pool allocation routine with malloc(), which looks like this:

inline void *pool_alloc(int len) {
    void *mem = _pool_base;

    if (len <= _pool_size) {
        _pool_size -= len;
        _pool_base += len;
        return mem;
    }

    _pool_base = static_cast<char *>(std::malloc(REALLOC_SIZE));
    mem = _pool_base;
    _pool_base += len;
    _pool_size = REALLOC_SIZE - len;
    return mem;
}

The allocator then is called like this:

Entry *entry = bins[h];
...
entry = static_cast<Entry *>(pool_alloc(sizeof(Entry)));
entry->word = word;
entry->next = NULL;
bins[h] = entry;

Is it possible to modify the pool_alloc routine such as I could wrap the malloc() with a shared pointer an define a custom deleter (maybe even skip the complete pool_alloc fct and just use a shared_ptr), something like

std::shared_ptr<Entry> entry((Entry *)malloc(sizeof(Entry)), freePtr());

struct freePtr {
    void operator()(void* x) {
        free(x); 
    }
};

Would be great if somebody could help me out on this. Thanks in advance!

Update:

I coded a simple memory pool class for my problem, so all pointers get destroyed automatically. The wrapped calloc() in the shared_ptr seems to work fine and works as expected. Valgrind reports no more memory leaks and errors.

Community
  • 1
  • 1
Andreas W. Wylach
  • 723
  • 2
  • 10
  • 31
  • The `pool_alloc` should only be allowed to allocate memory once, or you will have a memory leak there. Or of course keep track of all `malloc` calls done. – Some programmer dude Mar 02 '13 at 13:32
  • @JoachimPileborg: `pool_alloc` is called multiple times (the author of the code stated this) because the pointers at some point in the code get simply overwritten. I know of this problem already and will also change that. – Andreas W. Wylach Mar 02 '13 at 13:36

1 Answers1

0

OP writes:

I coded a simple memory pool class for my problem, so all pointers get destroyed automatically. The wrapped calloc() in the shared_ptr seems to work fine and works as expected. Valgrind reports no more memory leaks and errors.

In other words, changing the code fixed the bugs. :) This question could safely be deleted at this point.

Quuxplusone
  • 23,928
  • 8
  • 94
  • 159