Fix segfault in `opaque_handle` copy testing

Fortune for opaque_handle's current commit: Curse − 凶
master
Avril 3 years ago
parent d0558318b0
commit 437037e8c6
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -44,7 +44,7 @@ struct opaque_handle final {
: _impl(std::exchange(move._impl, nullptr)){} : _impl(std::exchange(move._impl, nullptr)){}
inline opaque_handle(const opaque_handle& copy) inline opaque_handle(const opaque_handle& copy)
: _impl(copy._impl : _impl(copy._impl
? std::addressof(copy._impl->clone()) //(copy._impl->try_clone() ?: throw opaque_not_copyable{}) ? copy._impl->try_clone() //(copy._impl->try_clone() ?: throw opaque_not_copyable{})
: nullptr){} : nullptr){}
constexpr ~opaque_handle() constexpr ~opaque_handle()
@ -177,13 +177,13 @@ constexpr inline opaque_handle make_opaque_handle(T* data, const HandleF& handle
struct object_handler final : opaque_handle_impl struct object_handler final : opaque_handle_impl
{ {
constexpr object_handler(const object_handler& c) noexcept(is_nothrow) constexpr object_handler(const object_handler& c) noexcept(is_nothrow)
: data(c.handler(data, opaque_handle_operation::Clone)) : data(c.handler(c.data, opaque_handle_operation::Clone))
, handler(c.handler){} , handler(c.handler){}
constexpr object_handler(object_handler&& m) noexcept constexpr object_handler(object_handler&& m) noexcept
: data(std::exchange(m.data, nullptr)) : data(std::exchange(m.data, nullptr))
, handler(m.handler){} , handler(m.handler){}
constexpr object_handler(T* data, const HandleF& handler) noexcept constexpr explicit object_handler(T* _data, const HandleF& handler) noexcept
: data(data) : data(_data)
, handler(handler){} , handler(handler){}
constexpr virtual ~object_handler() //noexcept(is_nothrow) constexpr virtual ~object_handler() //noexcept(is_nothrow)
@ -215,15 +215,16 @@ constexpr inline opaque_handle make_opaque_handle(T* data, HandleF&& handler) no
struct object_handler final : opaque_handle_impl struct object_handler final : opaque_handle_impl
{ {
constexpr object_handler(const object_handler& c) noexcept(is_nothrow && std::is_nothrow_copy_constructible_v<HandleF>) requires(std::is_copy_constructible_v<HandleF>) constexpr object_handler(const object_handler& c)
: data(c.handler(data, opaque_handle_operation::Clone)) noexcept(is_nothrow && std::is_nothrow_copy_constructible_v<HandleF>) requires(std::is_copy_constructible_v<HandleF>)
: data(c.handler(c.data, opaque_handle_operation::Clone))
, handler(c.handler){} , handler(c.handler){}
constexpr object_handler(object_handler&& m) noexcept constexpr object_handler(object_handler&& m) noexcept
: data(std::exchange(m.data, nullptr)) : data(std::exchange(m.data, nullptr))
, handler(std::move(m.handler)){} , handler(std::move(m.handler)){}
constexpr object_handler(T* data, HandleF&& handler) noexcept(is_nothrow_ctor) constexpr explicit object_handler(T* _data, HandleF&& handler) noexcept(is_nothrow_ctor)
: data(data) : data(_data)
, handler(std::move(handler)){} , handler(std::move(handler)){}
constexpr virtual ~object_handler() //noexcept(is_nothrow) constexpr virtual ~object_handler() //noexcept(is_nothrow)
@ -266,7 +267,7 @@ constexpr inline opaque_handle make_opaque_handle(T* data) noexcept
constexpr object_handler(object_handler&& m) noexcept constexpr object_handler(object_handler&& m) noexcept
: data(std::exchange(m.data, nullptr)){} : data(std::exchange(m.data, nullptr)){}
constexpr object_handler(T* data) noexcept constexpr explicit object_handler(T* data) noexcept
: data(data){} : data(data){}
constexpr virtual ~object_handler() //noexcept(is_nothrow) constexpr virtual ~object_handler() //noexcept(is_nothrow)

@ -1,8 +1,21 @@
//#define _GNU_SOURCE
#include <cstdlib>
#include <cstring>
#include <cstdio> #include <cstdio>
#include <unistd.h> #include <unistd.h>
#include "../include/opaque.hh" #include "../include/opaque.hh"
static void s_puts(const auto& string)
{
std::string_view str{string};
#ifdef DIRECT_WRITE
write(1, str.data(), str.size());
#else
printf("%.*s", (int)str.size(), str.data());
#endif
}
static void print_view(std::string_view ptr) static void print_view(std::string_view ptr)
{ {
@ -37,15 +50,26 @@ enum class moh_hck {
/// Example using `make_opaque_handle`, like would be done for a C interface /// Example using `make_opaque_handle`, like would be done for a C interface
template<moh_hck Create = moh_hck::Owned> template<moh_hck Create = moh_hck::Owned>
void use_moh() static void use_moh()
{ {
std::string* str = new std::string(__PRETTY_FUNCTION__); std::string* str = new std::string(__PRETTY_FUNCTION__);
constexpr auto v_print = [](const opaque_handle& v) {
print(*v);
{
auto copied = v;
s_puts("(copied)");
print(*copied);
s_puts("(moved)");
print(*std::move(copied));
}
};
if constexpr(Create != moh_hck::Owned) { if constexpr(Create != moh_hck::Owned) {
constexpr auto _h = [](std::string* ptr, auto op) noexcept { constexpr auto _h = [](std::string* ptr, auto op) noexcept {
if(ptr) { if(ptr) {
switch(op) { switch(op) {
case opaque_handle_operation::Clone: return new std::string(*ptr); case opaque_handle_operation::Clone: return new std::string(std::as_const(*ptr));
case opaque_handle_operation::Delete: delete ptr; break; case opaque_handle_operation::Delete: delete ptr; break;
} }
} }
@ -54,22 +78,59 @@ void use_moh()
if constexpr(Create == moh_hck::Template) { if constexpr(Create == moh_hck::Template) {
const opaque_handle v{make_opaque_handle<std::string, _h>(str)}; const opaque_handle v{make_opaque_handle<std::string, _h>(str)};
print(*v); v_print(v);
} else /*if constexpr(Create == moh_hck::Ref)*/ { } else /*if constexpr(Create == moh_hck::Ref)*/ {
const opaque_handle v{make_opaque_handle<std::string>(str, _h)}; const opaque_handle v{make_opaque_handle<std::string>(str, _h)};
print(*v); v_print(v);
} }
} else { } else {
const opaque_handle v{make_opaque_handle<std::string>(str, [](std::string* ptr, auto op) noexcept { const opaque_handle v{make_opaque_handle<std::string>(str, [](std::string* ptr, auto op) noexcept {
if(ptr) { if(ptr) {
switch(op) { switch(op) {
case opaque_handle_operation::Clone: return new std::string(*ptr); case opaque_handle_operation::Clone: return new std::string(std::as_const(*ptr));
case opaque_handle_operation::Delete: delete ptr; break; case opaque_handle_operation::Delete: delete ptr; break;
} }
} }
return static_cast<std::string*>(nullptr); return static_cast<std::string*>(nullptr);
})}; })};
print(*v); v_print(v);
}
s_puts("---\n");
}
// Testing a hypothetical C interface
extern "C" {
struct c_struct_example;
c_struct_example* cs_create(const c_struct_example* __restrict__ from);
void cs_free(c_struct_example* p);
void cs_print(const c_struct_example* p);
}
static void use_c_struct()
{
using type = c_struct_example;
auto* allocp = cs_create(nullptr);
const opaque_handle v{make_opaque_handle<type>(allocp, [](auto* ptr, auto op) noexcept {
if(ptr) {
switch(op) {
case opaque_handle_operation::Clone: return cs_create(ptr);
case opaque_handle_operation::Delete: cs_free(ptr); break;
}
}
return static_cast<type*>(nullptr);
})};
s_puts("> ");
cs_print(v);
{
auto copied = v;
s_puts("(copied)> ");
cs_print(copied);
s_puts("(moved)> ");
cs_print(std::move(copied));
} }
} }
@ -85,5 +146,52 @@ int main()
use_moh<moh_hck::Template>(); use_moh<moh_hck::Template>();
use_moh<moh_hck::Ref>(); use_moh<moh_hck::Ref>();
use_moh<moh_hck::Owned>(); use_moh<moh_hck::Owned>();
puts("\nUsing a C interface struct:");
use_c_struct();
return 0; return 0;
} }
extern "C" {
struct c_struct_example {
int i,j;
size_t sz;
char buf[256];
};
c_struct_example* cs_create(const c_struct_example* __restrict__ from)
{
auto* ptr = reinterpret_cast<c_struct_example*>(aligned_alloc(alignof(c_struct_example), sizeof(c_struct_example)));
//memset(ptr, 0, sizeof(c_struct_example);
if(!from) {
ptr->i = 10;
ptr->j = 11;
snprintf(ptr->buf, 256, "Hello from C interface");
} else {
//memcpy(ptr, from, sizeof(c_struct_example));
*ptr = *from;
ptr->i +=1;
ptr->j -=1;
snprintf(ptr->buf, 256, "Hello from copied C interface (from %p)", from);
}
return ptr;
}
void cs_print(const c_struct_example* p)
{
#ifdef DIRECT_WRITE
char ibuf[512];
size_t n = snprintf(ibuf, 512, "%s: (%d, %d)", p->buf, p->i, p->j);
write(1, ibuf, n < sizeof(ibuf) ? n : 511);
write(1, "\n", 1);
#else
printf("%s: (%d, %d)\n", p->buf, p->i, p->j);
#endif
}
void cs_free(c_struct_example* p)
{
free(p);
}
}

Loading…
Cancel
Save