C++ 自定义副本分配运算符使程序崩溃(C+;+;)

C++ 自定义副本分配运算符使程序崩溃(C+;+;),c++,image,sdl,copy-constructor,copy-assignment,C++,Image,Sdl,Copy Constructor,Copy Assignment,我正在创建一个自定义类来自动清理内存。该类包含指向SDL_曲面对象的指针,并在需要时调用其refcount。问题是,当我实现自定义复制分配操作符时,系统崩溃,代码如下: “xyz.exe中0x771a15de处的未处理异常:0xC0000005:访问冲突读取位置0xCCCD04。” 对象属性“address”突然获得值“0x0000ffff”,而使用默认的复制分配运算符时,它运行得非常正常。您使用的refcount不正确SDL_FreeSurface将减少refcount,当对空指针调用时,它是

我正在创建一个自定义类来自动清理内存。该类包含指向SDL_曲面对象的指针,并在需要时调用其refcount。问题是,当我实现自定义复制分配操作符时,系统崩溃,代码如下:

“xyz.exe中0x771a15de处的未处理异常:0xC0000005:访问冲突读取位置0xCCCD04。”


对象属性“address”突然获得值“0x0000ffff”,而使用默认的复制分配运算符时,它运行得非常正常。

您使用的refcount不正确
SDL_FreeSurface
将减少refcount,当对空指针调用时,它是一个no-op。因此,赋值运算符应如下所示:

const Image& Image::operator=(const Image& other){
    if (img != other.img){
        SDL_FreeSurface(img);
        img = other.img;
        if (img != NULL)
            img->refcount++;
    }
    return *this;
}
Image::~Image(){
    SDL_FreeSurface(img);
}
你的析构函数应该是这样的:

const Image& Image::operator=(const Image& other){
    if (img != other.img){
        SDL_FreeSurface(img);
        img = other.img;
        if (img != NULL)
            img->refcount++;
    }
    return *this;
}
Image::~Image(){
    SDL_FreeSurface(img);
}
此外,在默认构造函数中,应该将img初始化为空指针

Image::Image() :img(NULL) {}

请参阅本页倒数第二个示例:

我强烈建议您使用
std::shared_ptr
而不是手动进行引用计数。查看以获得正确行为的简单方法。jrok是正确的:
shared_ptr
与自定义deleter将更好地解决此问题。
SDL_FreeSurface
将减少refcount,并且当对null指针调用时,是不可操作的。因此,(在析构函数或赋值运算符中)无需检查null,减少refcount,或者将refcount与0进行比较。只需调用
SDL\u FreeSurface
。请参阅本页第二个到最后一个示例:事实上,仔细想想,这可能是您错误的根源。您正在递减refcount,然后调用SDL_FreeSurface,这会再次递减它。@BenjaminLindley:我认为您应该将您的评论变成一个答案。谢谢您Benjamin,我应该注意到这一点!现在它就像一个符咒!