0
class mapInfo
{
public:
    mapInfo();
    ~mapInfo();  
public:
    int dataType_m;

private:
    int *frequency;
};

//constructor is defined here.

    mapInfo::mapInfo() :
    dataType_m(0),
    frequency(NULL)
{
}  

//destructor is defined here

mapInfo::~mapInfo()
{
    free(frequency);
    frequency = NULL;
}

Result_t Maps::add(mapInfo &mapInfo_r)
{
    if (maps_mp == NULL)
    {
        numMaps_m = 1;
        maps_mp = (mapInfo *) calloc(1, sizeof(mapInfo));
    }
    else
    {
        numMaps_m++;
        maps_mp = (mapInfo *) realloc(maps_mp, numMaps_m*sizeof(mapInfo));
    }
    maps_mp[numMaps_m-1] = mapInfo_r; // Default copy constructor
    return 1;
}

While compiling with gcc8, getting the following compilation error. It looks like defining the destructor like above giving the compilation error for gcc8.

How to resolve this?

 error: 'void* realloc(void*, size_t)' moving an object of non-trivially copyable type 'class xyyz::mapInfo'; use 'new' and 'delete' instead [-Werror=class-memaccess]. 
Jyoti Raj Sharma
  • 91
  • 1
  • 3
  • 10
  • You don't show us the full code. Where is `realloc()` called actually? Also why are you not using `new` and `delete` as suggested, respectivly why are you messing with a raw pointer at all? – πάντα ῥεῖ Sep 03 '20 at 20:12
  • Added 'realloc' code as well. The 'realloc' is done from some other part of code. There is no substitute for 'realloc'. If I remove my destructor code part, it compiles successfully. – Jyoti Raj Sharma Sep 03 '20 at 20:18
  • This warning is telling you that you're doing something unsafe, namely using `realloc` on a non-trivially copyable type. The solution is not to use realloc. – Stephen Newell Sep 03 '20 at 20:25
  • Post a [mcve] please, What you originally shown [compiles just fine](http://coliru.stacked-crooked.com/a/8fd4d46ab8f77b50). `Result_t Maps::add(mapInfo &mapInfo_r)` of course can't be compiled, becase the declaration is missing. – πάντα ῥεῖ Sep 03 '20 at 20:25
  • I’m positively surprised that gcc warns you here. But **GCC is correct**. Don’t do this, it’s illegal. Heed the suggestion. In fact, it’s not at all clear why you’re using pointers here anyway. Use `std::vector`s for `maps_mp` and `frequency`. – Konrad Rudolph Sep 03 '20 at 20:27
  • 1
    Can i make my destructor trivially copyable? If so, gcc8 will compile with 'realloc' too. – Jyoti Raj Sharma Sep 03 '20 at 20:28
  • @JyotiRajSharma “destructor trivially copyable” is not a meaningful statement. – Konrad Rudolph Sep 03 '20 at 20:29
  • It's the type that's trivially copyable or not. The requirements are available here: https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable. – Stephen Newell Sep 03 '20 at 20:30
  • Unrelated, but your `calloc` is a problem too, since you never call the `mapInfo` ctor. – Stephen Newell Sep 03 '20 at 20:31

2 Answers2

2

That’s simply not proper C++. Rewrite your code as follows (I’m guessing here with regards to the type of frequency, but definitely don’t use free on it):

#include <vector>

class map_info
{
public:
    map_info();

private:
    int data_type;
    std::vector<int> frequency;
};
std::vector<map_info> maps_mp;

map_info::map_info() : data_type(0), frequency() {}

// …

void maps::add(map_info& map_info)
{
    maps_mp.push_back(map_info);
}

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
1
    maps_mp = (mapInfo *) realloc(maps_mp, numMaps_m*sizeof(mapInfo));

This is not sensible. You can't just move an object from one aree of memory to another if that object is non-trivial.

For example, consider a string object that keeps a pointer to the string. It could look like this:

class MyString
{
    char* inner_ptr;
    char buf[64];

    ...
};

And it might have a constructor like this:

MyString::MyString (const char* j)
{
     if (strlen(j) < 64)
         inner_ptr = buf;
     else
         inner_ptr = malloc (strlen(j) + 1);
     strcpy(inner_ptr, j);
}

And a destructor like this:

MyString::~MyString()
{
     if (buf != inner_ptr)
         free (inner_ptr);
}

Now, think about what happens if you call relloc on an array of these. The short strings will still have their inner_ptrs pointing to the old object's buffer, which you just deallocated.

The error message explains this issue reasonable well. It is simply not legal to use realloc to move a non-trivial object. You have to construct a new object because the object needs a chance to handle the change in its address.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278