3
votes

Suppose, I have the following code:

class Data
{
  private:
    int *m_arr;
    int m_size;
    bool m_deAlloc;
  public:
    Data(int *arr, int size): m_arr(arr), m_size(size), m_deAlloc(false) {}
    ~Data(){ if(m_deAlloc) delete[] m_arr; }
...
};

void foo(Data &d)
{
   // uses d ...
}  

void foo_wrapper(int *arr, int size)
{
   Data d(arr, size); // should I create it as new Data(arr, size)?

   foo(d); // asynchronous call...

} // ~Data() will be called but m_arr array will not be erased...

int main()
{
  int *arr = new int[...];
  ...
  foo_wrapper(arr,...); // internally calls foo asynchronously...
  ...
  // wait for foo execution completion....
  ...
  delete[] arr;
}

I tried it with gcc and it works apparently but I think it's not a valid program as "Data" reference passed to "foo" from "foo_wrapper" can be invalid as destructor of the object passed might get called before foo has finished executing (asynchronous execution). Although I don't delete data (m_arr) but still what happens with the object reference when destructor gets called?

Does the C++ (gcc) compiler just calls the destructor. For example when a destrutor for object "d" is called, does it relocate memory allocation for object "d" and set "d" to some invalid reference?

2
how do you allocate arr pointer? - billz
Show real main, it depends how array initialized before passing to foo_wrapper - Denis Ermolin
delete m_arr[]; is wrong, it shall be delete [] m_arr; - billz
@billz I have edited the question. - usman

2 Answers

1
votes

In this case, the Data instance (d) you pass to foo() will just be placed on the main thread's stack -- it can certainly be destructed and out of scope (e.g. potentially reused as the main thread continues execution) before foo() returns. It is undefined behavior. Even if the allocation were not overwritten, you should not play with a destructed object.

One way or another, you need to ensure the parameter d is valid and not destructed until after foo() has returned.

1
votes

Depends how array was initialized. If you initialize it on stack then this is undefined behavior because if foo() is asynchronous then it's true that array can be destroyed before foo() finish. But if it allocated on the heap then it's safe if you delete array inside foo, or after foo call.

But it's safer to use std::shared_ptr. It's perfect to manage pointers between asynchronous calls.