0

Consider the following data structure for managing memory buffers as table:

#include <cstdlib>
#include <cstring>
#include <unordered_map>
 
class BufferItem {
    char* data = nullptr;
    size_t data_size = 0;
public:
    BufferItem () = default;
    BufferItem (size_t size) : data_size(size) {
        data = (char*) std::calloc (size, 1);
        printf("calloc %p\n", data);
    }
    ~BufferItem () { std::free (data); }
    inline bool ok () { return data != nullptr; }
};
 
class Buffer {
public:
    using key_t = const char*;
private:
    std::unordered_map<key_t, BufferItem> data;
public:
    inline bool exists (key_t key) { return data.find (key) != data.end(); }
    inline bool create (key_t key, size_t size) {
        if (!exists (key)) data[key] = BufferItem (size);
        return data[key].ok();
    }
};

/* somewhere outside */
Buffer buf;
buf.create("ip_buf", 16);
buf.create("port_buf", 16);

For some reason, calloc() returns same address:

calloc 000000000338e800
calloc 000000000338e800

Why does this happen? I build with MinGW64 gcc 10.1.0.

trexxet
  • 176
  • 3
  • 14
  • 5
    Implement the rule of three and you'll probably see different results. Right now you're performing shallow copies of your `BufferItem`s. – Stephen Newell Nov 08 '20 at 22:29
  • 1
    Put a print statement in your `BufferItem` destructor – smac89 Nov 08 '20 at 22:30
  • 2
    Perhaps the 1st instance is being destroyed before the 2nd instance is created? See [The rule of three/five/zero](https://en.cppreference.com/w/cpp/language/rule_of_three): `If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.` – paulsm4 Nov 08 '20 at 22:30
  • Fine example of why people don't write C++ code like this in the industry anymore. `calloc` has no advantages over `std::vector`. With `malloc` you can always make the oft-questionable claim that, "Initialization costs too much." That thin argument goes away with `calloc`. Use `std::vector` and watch the problem just... go away. – user4581301 Nov 08 '20 at 22:35
  • 1
    You must implement a copy constructor and an assignment operator for your `BufferItem`, see the linked question for more information. In your current code, attempt to clear the `data` map and watch the shown code crash spectacularly. – Sam Varshavchik Nov 08 '20 at 22:37
  • Thank you all. I put a printf into destructor and see that BufferItem get destroyed before next one is created. Should have remembered rule of three :) – trexxet Nov 08 '20 at 22:42

0 Answers0