Skip to content

[Issue]: HIPCC: cannot call unique_ptr destructor from device code #296

@jakub-homola

Description

@jakub-homola

Problem Description

The relatively simple program

#include <memory>

template<typename T>
struct data
{
    T val;
};

template<typename T>
struct manager
{
    manager();
    ~manager();

    std::unique_ptr<data<T>> d;
};

template<typename T>
manager<T>::manager() = default;

template<typename T>
manager<T>::~manager() = default;

template struct manager<double>;

int main()
{
}

cannot be compiled with hipcc source.cpp -o program.x. This is the error I am getting:

source0.cpp:12:5: error: reference to __host__ function '~unique_ptr' in __host__ __device__ function
    manager();
    ^
source0.cpp:21:13: note: in defaulted default constructor for 'manager<double>' first required here
manager<T>::manager() = default;
            ^
source0.cpp:28:17: note: in instantiation of member function 'manager<double>::manager' requested here
template struct manager<double>;
                ^
/usr/lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/bits/unique_ptr.h:398:7: note: '~unique_ptr' declared here
      ~unique_ptr() noexcept
      ^
1 error generated when compiling for gfx90a.

Why is it even trying to make the constructor a device function?

Furthermode, the 4 very similar programs written below compile just fine.

Am I doing something wrong? What is the problem here?

Thanks for any help,

Jakub


Here I don't use the =default, but instead "implement" the constructor and destructor:

#include <memory>

template<typename T>
struct data
{
    T val;
};

template<typename T>
struct manager
{
    manager();
    ~manager();

    std::unique_ptr<data<T>> d;
};

template<typename T>
manager<T>::manager() {}

template<typename T>
manager<T>::~manager() {}

template struct manager<double>;

int main()
{
}

Here I default the constructor and destructor directly inside of the struct instead of separately:

#include <memory>

template<typename T>
struct data
{
    T val;
};

template<typename T>
struct manager
{
    manager() = default;
    ~manager() = default;

    std::unique_ptr<data<T>> d;
};

template struct manager<double>;

int main()
{
}

Here is the code without templates:

#include <memory>

struct data
{
    double val;
};

struct manager
{
    manager();
    ~manager();

    std::unique_ptr<data> d;
};

manager::manager() = default;

manager::~manager() = default;

int main()
{
}

And here, the struct is not explicitly instantiated manually, but instead I create an instance in main, which instantiates the template:

#include <memory>

template<typename T>
struct data
{
    T val;
};

template<typename T>
struct manager
{
    manager();
    ~manager();

    std::unique_ptr<data<T>> d;
};

template<typename T>
manager<T>::manager() = default;

template<typename T>
manager<T>::~manager() = default;

int main()
{
    manager<double> m;
}

Operating System

SLES 15-SP5

CPU

AMD EPYC 7A53

GPU

AMD Instinct MI250X

ROCm Version

ROCm 6.0.3

ROCm Component

HIP

Steps to Reproduce

No response

(Optional for Linux users) Output of /opt/rocm/bin/rocminfo --support

No response

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions