change pointer in std::unique_ptr without destroy it - c++

I have C++ code that uses raw pointer with C functions malloc, free and realloc.
I am thinking to change it to smart pointer, but I really want to keep the realloc functionality, because I believe it is much better than new, since it does not need to "move" the contents every time.
How I can refactor this with std::unique_ptr?
Here is some pseudo code (I realize this code is not 100% safe. In fact I never tried to compile it)
class Demo{
char *ptr;
Demo(size_t size) : ptr( malloc(size) ){}
bool resize(size_t size){
char *ptr_new = realloc(ptr, size);
if (ptr_new == nullptr){
return false; // fail
}
// here is tricky part with std::unique_ptr,
// ptr is already deleted...
ptr = ptr_new;
return true;
}
};

The way to reassign a pointer without deleting it is to use release():
auto old_ptr = unique.release();
unique.reset(new_ptr);
So in your code that would be something like:
struct free_deleter {
void operator(void* p) const { free(p); }
};
std::unique_ptr<char, free_deleter> ptr; // NB: malloc must be paired with free, not delete
bool resize(size_t size) {
char* ptr_new = realloc(ptr.get(), size);
if (!ptr_new) {
return false;
}
ptr.release();
ptr.reset(ptr_new);
return true;
}

Related

Placement New on already existing object in SharedMemory

I have two programs. The first allocates a Shared-Memory file and the second reads from it.. I am using placement-new to place objects into this memory guaranteeing that the objects do NOT use new or allocate any memory outside of the Shared-Memory file.
My Array structure:
template<typename T, size_t Size>
struct SHMArray {
SHMArray() : ptr(elements) {}
SHMArray(const SHMArray& other) { std::copy(other.begin(), other.end(), begin()); }
SHMArray(SHMArray&& other)
{
std::swap(other.ptr, ptr);
std::fill_n(ptr.get(), Size, T());
}
~SHMArray()
{
std::fill_n(ptr.get(), Size, T());
}
constexpr bool empty() const noexcept
{
return Size == 0;
}
constexpr size_type size() const noexcept
{
return Size;
}
T& operator[](std::size_t pos)
{
return *(ptr.get() + pos);
}
constexpr const T& operator[](std::size_t pos) const
{
return *(ptr.get() + pos);
}
T* data() noexcept
{
return ptr.get();
}
constexpr const T* data() const noexcept
{
return ptr.get();
}
private:
offset_ptr<T> ptr;
T elements[];
};
Program 1:
int main()
{
//Allocate a shared memory file of 1mb..
auto memory_map = SharedMemoryFile("./memory.map", 1024 * 1024, std::ios::in | std::ios::out);
memory_map.lock();
//Pointer to the shared memory.
void* data = memory_map.data();
//Place the object in the memory..
SHMArray<int, 3>* array = ::new(data) SHMArray<int, 3>();
(*array)[0] = 500;
(*array)[1] = 300;
(*array)[2] = 200;
memory_map.unlock(); //signals other program it's okay to read..
}
Program 2:
int main()
{
//Open the file..
auto memory_map = SharedMemoryFile("./memory.map", 1024 * 1024, std::ios::in | std::ios::out);
memory_map.lock();
//Pointer to the shared memory.
void* data = memory_map.data();
//Place the object in the memory..
//I already understand that I could just cast the `data` to an SHMArray..
SHMArray<int, 3>* array = ::new(data) SHMArray<int, 3>();
for (int i = 0; i < array.size(); ++i)
{
std::cout<<(*array)[i]<<"\n";
}
memory_map.unlock(); //signals other program it's okay to read..
}
Program One placed the SHMArray in memory with placement new. Program Two does the same thing on top of program one's already placed object (overwriting it). Is this undefined behaviour? I don't think it is but I want to confirm.
Neither program calls the destructor array->~SHMVEC(); I also don't think this leaks as long as I close the MemoryMapped file then it should all be fine.. but I want to make sure this is fine. If I ran the programs again on the same file, it shouldn't be a problem.
I am essentially making the assumption that placement new is working as if I placed a C struct in memory in this particular scenario via: struct SHMArray* array = (struct SHMArray*)data;.. Is this correct?
I am essentially making the assumption that placement new is working
as if I placed a C struct in memory in this particular scenario via:
struct SHMArray* array = (struct SHMArray*)data;.. Is this correct?
No, this is not correct. Placement new also invokes the object's appropriate constructor. "struct SHMArray* array = (struct SHMArray*)data;" does not invoke any object's constructor. It's just a pointer conversion cast. Which does not invoke anyone's constructor. Key difference.
In your sample code, you do actually want to invoke the templated object's constructor. Although the shown example has other issues, as already mentioned in the comments, this does appear to be what needs to be done in this particular situation.
But insofar as the equivalent of placement new versus a pointer cast, no they're not the same. One invokes a constructor, one does not. new always invokes the constructor, whether it's placement new, or not. This is a very important detail, that's not to be overlooked.

In C++11, how can I call new and reserve enough memory for the object?

I have a class that is described that way :
class Foo {
int size;
int data[0];
public:
Foo(int _size, int* _data) : size(_size) {
for (int i = 0 ; i < size ; i++) {
data[i] = adapt(_data[i]);
}
}
// Other, uninteresting methods
}
I cannot change the design of that class.
How can I create an instance of that class ? Before calling the constructor, I have to make it reserve enough memory to store its data, so it has to be on the heap, not on the stack. I guess I want something like
Foo* place = static_cast<Foo*>(malloc(sizeof(int) + sizeof(int) * size));
*place = new Foo(size, data); // I mean : "use the memory allocated in place to do your stuff !"
But I can't find a way to make it work.
EDIT : as commentators have noticed, this is not a very good overall design (with non-standards tricks such as data[0]), alas this is a library I am forced to use...
You could malloc the memory for the object and then use a placement new to create the object in the previously allocated memory :
void* memory = malloc(sizeof(Foo) + sizeof(int) * size);
Foo* foo = new (memory) Foo(size, data);
Note that in order to destroy this object, you can't use delete. You would have to manually call the destructor and then use free on the memory allocated with malloc :
foo->~Foo();
free(memory); //or free(foo);
Also note that, as #Nikos C. and #GManNickG suggested, you can do the same in a more C++ way using ::operator new :
void* memory = ::operator new(sizeof(Foo) + sizeof(int) * size);
Foo* foo = new (memory) Foo(size, data);
...
foo->~Foo();
::operator delete(memory); //or ::operator delete(foo);
You have a library that does this thing but doesn't supply a factory function? For shame!
Anyway, while zakinster's method is right (I'd directly call operator new instead of newing an array of chars, though), it's also error-prone, so you should wrap it up.
struct raw_delete {
void operator ()(void* ptr) {
::operator delete(ptr);
}
};
template <typename T>
struct destroy_and_delete {
void operator ()(T* ptr) {
if (ptr) {
ptr->~T();
::operator delete(ptr);
}
}
};
template <typename T>
using dd_unique_ptr = std::unique_ptr<T, destroy_and_delete<T>>;
using FooUniquePtr = dd_unique_ptr<Foo>;
FooUniquePtr CreateFoo(int* data, int size) {
std::unique_ptr<void, raw_delete> memory{
::operator new(sizeof(Foo) + size * sizeof(int))
};
Foo* result = new (memory.get()) Foo(size, data);
memory.release();
return FooUniquePtr{result};
}
Yes, there's a bit of overhead here, but most of this stuff is reusable.
If you really want to be lazy simply use a std::vector<Foo>. It will use more space (I think 3 pointers instead of 1) but you get all the benefits of a container and really no downsides if you know it is never going to change in size.
Your objects will be movable given your definition so you can safely do the following to eliminate reallocation of the vector during initial fill...
auto initialFooValue = Foo(0, 0)
auto fooContainer = std::vector<Foo>(size, initialFooValue);
int i = 0;
for (auto& moveFoo : whereverYouAreFillingFrom)
{
fooContainer[i] = std::move(moveFoo);
++i;
}
Since std::vector is contiguous you can also just memcopy into it safely since your objects are trivially-copyable.
I think a good C++ solution is to get raw memory with new and then use placement new to embed your class into it.
getting raw memory works like this:
Foo *f = static_cast<Foo *>(operator new(sizeof(Foo));
constructing the object in received memory works like this:
new (f) Foo(size, data); // placement new
remember that this also means that you have to manually clean up the place.
f->~Foo(); // call the destructor
operator delete(f); // free the memory again
My personal opinion is, that it is bad to use malloc and free in newly written C++ code.

C++ check if pointer is valid?

I'm having problems with valid pointers in C++. I'm using one object in different threads, so I can't just set the pointer to NULL and return. Here's what I'm trying:
int main()
{
char *ptr = new char[1024]; //assume PTR = 0x12345678
changePtr(ptr); //after calling this,
//ptr is not NULL here.
return 0;
}
void changePtr(char *ptr)
{
delete [] ptr; //ptr = 0x12345678
ptr = NULL; //ptr = NULL
}
How can I change ptr to NULL for both functions?
change the signature of changePtr to:
void changePtr(char **ptr)
{
delete [] *ptr; //ptr = 0x12345678
*ptr = NULL; //ptr = NULL
}
And call it using:
changePtr(&ptr);
In C++, use reference parameter:
void changePtr(char *&ptr) {
delete [] ptr; //ptr = 0x12345678
ptr = NULL; //ptr = NULL
}
In C, you need to pass pointer to pointer, which is basically same thing with less pretty syntax.
You do not need to change the calling code. But you must give a modifiable variable as argument when calling, can't give for example NULL or nullptr, same as you can't do &NULL.
If you really want to manage memory in such a complex, error-prone way, then pass a reference to, rather than a copy of, the caller's pointer:
void changePtr(char *&ptr)
// ^
Much better would be to use a smart pointer; they are designed so that it's very difficult to leave them dangling when the target is deleted:
int main()
{
std::unique_ptr<char[]> ptr(new char[1024]); //assume PTR = 0x12345678
changePtr(ptr); //after calling this,
//ptr is empty here.
return 0;
}
void changePtr(std::unique_ptr<char[]> & ptr)
{
ptr.reset();
}
although if I wanted a dynamic array, I'd avoid new altogether and use std::vector.
I have seen a great many questions about how to check a pointer for validity. A large number of these questions have been about Windows. There may not be a general way to check in C++, but for a Windows specific solution the following seems to work on my system:
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv)
{
MEMORY_BASIC_INFORMATION lpBuffer;
int cActualBytes;
cActualBytes = VirtualQuery(&main, &lpBuffer, sizeof(lpBuffer)); // Can we get info about main?
if (!cActualBytes)
{
printf("Nope, you can't do that \n");
return 2;
}
if (cActualBytes != sizeof(lpBuffer))
{
printf("Surprise! Expected %d bytes, got %d\n", sizeof(lpBuffer), cActualBytes);
}
printf("Information for main\n");
printf("---------------------------\n");
printf("C reports pointer %p, Virtual Alloc sees it as %p\n",&main,lpBuffer.BaseAddress);
return 0;
}

Object allocation on stack or heap

I'm trying to make a mechanism that could tell where the object of the class is allocated.
Thought about making a flag in the class, but it's not possible to set a value because object's lifetime is not started during the call of "new" operator.
Is it possible in C++ to tell if an object is on stack or heap (runtime)?
There is no portable way to do this, but if we assume you have a limited amount of system types where you are going to do this on, you could try the following:
Take the address of some local variable in main (or other "low in the callstack"). Store this in a global variable, lets call char *stackbase;
Then take the address of a local variable in your function that you are checking in, let's call it char *stacktop;
Now, if we have a char *obj = reinterpret_cast<char *>(object_in_test);, then:
if (obj > stacktop && obj < stackbase) on_stack = true;
else on_stack = false;
Note that there are SEVERAL flaws with this:
It's technically undefined behaviour. It will work on most systems, because the whole memory space is contiguous. But there are systems where the stack and other sections of memory have separate "address spaces", which means that two pointers to different types of memory can have the same address.
Threads will need to have a "per thread stackbase".
The stack is assumed to "grow towards zero" (if not, you'll have to invert the > and < in the if.
Global variables will be seen as not on stack.
USE AT YOUR OWN RISK!
I fully expect to have to delete this answer as it will be downvoted by language lawyers, despite the disclaimer below.
I have been doing some experimentation, and have discovered that this seems to work for being able to always tell at runtime if an object was allocated on the stack or not.
The interface is as follows:
#ifndef HEAPAWARE_H
#define HEAPAWARE_H
#include <cintttypes>
class HeapAware
{
public:
HeapAware();
void *operator new(std::size_t size);
void *operator new[](std::size_t size);
void operator delete(void *ptr, std::size_t);
void operator delete[](void *ptr, std::size_t);
bool is_on_heap() const { return on_heap; }
std::ptrdiff_t get_heap_array_index() const { return heap_array_index; }
private:
const bool on_heap;
const std::ptrdiff_t heap_array_index;
static thread_local HeapAware * last_alloc;
static thread_local std::size_t allocated_size;
};
#endif
And the implementation is:
void *HeapAware::operator new(std::size_t size)
{
auto result = last_alloc = reinterpret_cast<HeapAware*>(malloc(size));
allocated_size = 1;
return result;
}
void *HeapAware::operator new[](std::size_t size)
{
auto result = last_alloc = reinterpret_cast<HeapAware*>(malloc(size));
allocated_size = size;
return result;
}
void HeapAware::operator delete(void *ptr, std::size_t)
{
free(ptr);
}
void HeapAware::operator delete[](void *ptr, std::size_t)
{
free(ptr);
}
HeapAware::HeapAware():on_heap(this>=last_alloc && this<last_alloc+allocated_size),heap_array_index(allocated_size>1?this-last_alloc:-1)
{
}
thread_local HeapAware * HeapAware::last_alloc = nullptr;
thread_local std::size_t HeapAware::allocated_size = 0;
This seems to always work correctly. For arrays allocated on the heap, the index of the entry is also available. For values that are allocated on the stack, or for entries that are just allocated singly, the get_heap_array_index() function returns -1.
The assumption that this code makes is that the new operator is called immediately before construction on any given thread. This assumption seems to hold true for everything I have tried, however.

Swapping an object within itself

I'm trying to swap an object within itself. It works but when I add a destructor it gives me a double free error. Is there a way to prevent this? The method I'm talking about is void swap(SimpleArray &object).
(Sorry if you read this before I had the wrong info in my post...)
#include "TestType.h"
class SimpleArray {
private:
TestType* pArray;
//TestType* temp;
public:
SimpleArray(TestType *array)
{
this->pArray = array;
}
~SimpleArray() { delete[] pArray; }
SimpleArray() { pArray = 0;}
SimpleArray(const SimpleArray& arg){ pArray = arg.pArray; }
~SimpleArray() { delete[] pArray; }
TestType * get() const{ return pArray; }
bool isNonNull() const { return pArray != 0; }
//TestType* pArray;
void reset(TestType*& p) {this->pArray = p; }
void reset() { pArray = 0; }
void swap(SimpleArray &object) { SimpleArray temp; temp = object; object = *this; *this = temp;}
TestType * release() { pArray = 0; return pArray; }
TestType& getReference(int a) { return *pArray; }
};
This works but once I add the destructor it gives me a "double free or corruption error". How do I solve this? Here's the function in main where it messes up.
bool testGetReleaseSwap() {
SimpleArray array1;
if (array1.get() != 0)
return false;
TestType* directArray1 = new TestType[100];
array1.reset(directArray1);
if (array1.get() != directArray1)
return false;
TestType* directArray2 = new TestType[50];
SimpleArray array2(directArray2);
array1.swap(array2);
if (array1.get() != directArray2 || array2.get() != directArray1)
return false;
array2.swap(array1);
if (array1.get() != directArray1 || array2.get() != directArray2)
return false;
array1.swap(array1);
if (array1.get() != directArray1)
return false;
if (array1.release() != directArray1 || array2.release() != directArray2)
return false;
if (array1.get() != 0 || array2.get() != 0)
return false;
delete[] directArray1;
delete[] directArray2;
return true;
}
The trivial way out here is to invoke temp.release() at the end if your swap method to prevent double deletion.
The underlying issue is much deeper, though. In C++ it is crucial to always maintain strict semantics of who owns something, for example a memory region that requires deletion.
A frequent pattern is that the object that allocates something is also responsible for cleaning up and no one else. This fits nicely with SimpleArray, but the copy constructor breaks it because it multiplies the number of owners!
To implement shared data semantics you have to invest more work (reference counting etc.) or you have to forbid array copying and make the copy constructor private.
A clean way to fix up swap to work without copying the object would be:
void swap(SimpleArray &object) {
TestType* temp = object.pArray;
object.pArray = this->pArray;
this->pArray = temp;
}
(std::swap(object.pArray, pArray); works as well)
Because to swap the memory regions of the array fits nicely with a single-owner pattern, what went wrong here is only the use of the full object copy.
You should read up on resource management and ownership semantics in C++. Your code will always be error prone unless you absolutely know who owns what.
It seems to me that you are trying to implement a class that has shallow copy semantics (and possibly copy-on-write). To do that successfully you need to track how many other owners of the shared data are still around and need to destroy the owned object, when that count reaches zero. You can either use a std::shared_ptr for that or implement the reference counting yourself.
As for the real problem in that specific example, look at what you copy constructor is doing. It is not copying but simply taking another reference (a pointer to be specific) to the object that is already owned by its argument. That by itself already enough to get a double free and your swap testcase is simply exposing that issue.