1

Memory allocated in one dynamic library and then deleted in another library can often trigger problems as the Memory allocation and deallocation across dll boundaries shows. My question is related to objects of auto_ptr type. This type of object provided by a dll is very tricky as the program that uses the dll will delete the object automatically. However, it often happens that some memory reallocation operations may happen to the auto_ptr type object in the dll library. Therefore writing a function that destroys the auto_ptr type object is necessary. First, I give the following example, which illustrates the importance of destroying auto_ptr type objects in a dll library.

The header file for the .dll library is as follows:

dll.h
class __declspec(dllexport) Image
{
public:
    Image()
    {
        mem = NULL;
    }
    ~Image()
    {
        std::cout<<"Image is being deleted!"<<std::endl;

        delete []mem;
        mem = NULL;

    }

    int *mem;

};

typedef std::auto_ptr<Image> ImagePtr;



class __declspec(dllexport) ImageReader
{
public:
    void memory_reset(Image &img)
    {
img.mem = new int [20*30];

    }
};

The executable program that invokes the dll library is as follows:

#include "dll.h"
#include <iostream>
#include <vector>
#include <numeric>
#include <iostream>
#include <algorithm>
#include <functional>
#include <iterator>

int main()
{
    ImagePtr my_img(new Image());
    ImageReader bmp_reader;
    bmp_reader.memory_reset(*my_img);

    return 0;

}

If the run time library invoked is statically linked (Multi-threaded Debug (/MTd)), an error will occur when runing the executable program: enter image description here

In order to solve this problem, the auto_ptr object must be deleted by the library. Then the question arises: what is the best way of deleting this type of object? The way I can think of is to provide a Global function that can delete the auto_ptr object:

void Fun_destroy_memory(Image &img)
{
    img.~Image();
}

So the executable program will become:

int main()
{
    ImagePtr my_img(new Image());
    ImageReader bmp_reader;
    bmp_reader.memory_reset(*my_img);
    Fun_destroy_memory(*my_img);

    return 0;

}   

I do not know whether there are other solutions in this situation. Additionally, I would like to know wheter it is a good practice of invoking class destructor directly as I did in Fun_destroy_memory. Many thanks!

Community
  • 1
  • 1
feelfree
  • 11,175
  • 20
  • 96
  • 167
  • Invoking a destructor directly is a bad idea. Particularly with auto_ptrs, as we know that the auto_ptr will attempt to free this memory at some point. If the destructor calls the delete operation on some managed object it owns, you will double free this memory. – MobA11y May 23 '13 at 17:19
  • Consider using `std::unique_ptr<,>` instead (C++11 only) as it will allow you to specify a particular delete functor type and perform the delete at whichever location you want. – cdhowie May 23 '13 at 17:24

1 Answers1

2

auto_ptrs are in charge of managing the object they represent. The object they are managing will get freed when the auto_ptr goes out of scope. You do not have control of the "lifetime" of any variable you do not create with 'new'. As such, there is no way to destroy this 'auto_ptr', it will simply go out of scope. If you're having scope issues with this object, and you are positive this is the problem(clearly I am not convinced), you can outline sections of code with arbitrary scope resolution operators, to manage the scope of certain variables. I copied your code to create an example.

int main()
{
    //Do some work that doesn't need an ImagePtr
    ImageReader bmp_reader;
    { 
        ImagePtr my_img(new Image());
        bmp_reader.memory_reset(*my_img);
    } // the my_img pointer is no longer in scope and it's manage object will be freed          
    return 0;
}

Note that I do not necessarily recommend doing this, I frankly think it looks terrible and that your problem is elsewhere. But if you are absolutely convinced that managing the lifetime of 'my_img' in comparison to 'bmp_reader' will help, this is how you do it.

Why not just modify memory_reset. If an object/function takes "control" of an object, and does something with its managed memory it is its responsibility to make sure that memory is freed before it assigns the value of this pointer to something else. I would recommend the following.

void memory_reset(Image &img)
{
    delete[] img.mem; //add this line
    img.mem = new int [20*30];
}

Also, note that mixing managed/garbage collecting/smart pointers in the same environment with new/delete memory management type of schemes is generally considered poor programming practice.

MobA11y
  • 18,425
  • 3
  • 49
  • 76