使用unique_ptr的分段错误

时间:2019-11-21 08:04:52

标签: c++ segmentation-fault unique-ptr

我试图使用unique_ptr而不是自己分配内存。 我有以下代码:

class Album {
...
public:
    Add(Song* song);
...
}

void func(){
    ...
    std::unique_ptr<Album> album = std::unique_ptr<Album>{new Album()};
    std::unique_ptr<Song> song = std::unique_ptr<Song>{new Song(soundtrack.data(), soundtrack.length())};
    album->Add(song.get());
    ...
}

该行出现细分错误:

album->Add(song.get());

我尝试了多种变体来获取指针,包括std :: move和make_unique,但是也许我不明白unique_ptr如何很好地解决它。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

问题如下

class Album {
...
public:
    Add(Song* song);
...
}

void func(){
    ...
    std::unique_ptr<Album> album = std::unique_ptr<Album>{new Album()};
    std::unique_ptr<Song> song = std::unique_ptr<Song>{new Song(soundtrack.data(), soundtrack.length())};
    album->Add(song.get());
    ...
    // Here the object song gets destructed. This means that the underlying Song gets destructed.
    // So right after leaving func() the pointer that was returned by song.get() now points to non-allocated memory containing random bits at worst case.
}

所以一种可能的解决方案是...

class Album {
...
public:
    Add(std::unique_ptr<Song>&& song); // you still need to move song inside Add(...)
...
}

void func(){
    ...
    std::unique_ptr<Album> album = std::unique_ptr<Album>{new Album()};
    std::unique_ptr<Song> song = std::unique_ptr<Song>{new Song(soundtrack.data(), soundtrack.length())};
    album->Add(std::move(song)); //here song is intended  to be moved inside Add(...)
    ...
    // If moved inside Add(...) song points to nullptr here.
}

答案 1 :(得分:1)

您提供的代码可以编译并正常运行-因此,您未提供的部分肯定存在问题-我怀疑Add()中的代码或其返回类型,或者以后将指针用作{{3}怀疑。工作示例在gdbonline上:
necktschnagge

首先,我问一个问题,您想通过使用std::unique_ptr获得的优势?考虑到唯一指针并不能保证有一个指针-在Add()内,您必须检查nullptr! 我认为从您的用法来看,您不想使用std::unique_ptr

关键在于,std::unique_ptr仅具有唯一所有权。其中之一:

  • func() ::本地范围
  • album::Add() :: parameter_scope

拥有它。

由于您未使用std::move(),因此所有权保留在func()中,并且将在func()的末尾被销毁。为避免这种情况,您最好使用song.release()(请参见https://onlinegdb.com/r1oyXGK2S)。