C++ moving a unique_ptr to a struct member - c++

I have the following program -
#include <iostream>
#include <memory>
class Person
{
public:
Person(const std::string& name):
name(name) { }
~Person() { std::cout << "Destroyed" << std::endl; }
std::string name;
};
typedef struct _container
{
std::unique_ptr<Person> ptr;
}CONTAINER;
void func()
{
CONTAINER* c = static_cast<CONTAINER*>(malloc(sizeof(CONTAINER)));
std::unique_ptr<Person> p(new Person("FooBar"));
c->ptr = std::move(p);
std::cout << c->ptr->name << std::endl;
}
int main()
{
func();
getchar();
return 0;
}
The program prints "FooBar". I expect the program to print "Destroyed" when func() return but it does not. Can someone help me with why that would not be happening in this case?

You've actually got undefined behaviour here.
You cant just cast a malloc'd buffer to an object type. The constructors are never called and your member variables are in an invalid state.
You need to do either:
void func()
{
CONTAINER c;
std::unique_ptr<Person> p(new Person("FooBar"));
c.ptr = std::move(p);
std::cout << c.ptr->name << std::endl;
}
Or
void func()
{
CONTAINER * c = new CONTAINER();
std::unique_ptr<Person> p(new Person("FooBar"));
c->ptr = std::move(p);
std::cout << c->ptr->name << std::endl;
delete c;
}
or if you really want to use malloc - you'll need to use placement new to get the right behaviour - but usually you dont want that, so I wont elaborate for now...

You forget to add this line at the end of func().
delete c;
Here is the test (ideone).
c is a raw pointer. It is not a smart pointer.
Thus, you have to delete it manually.
Deleting c will automatically delete CONTAINER::ptr because CONTAINER::ptr is a unique pointer.
However, you have malloc yourself, the more proper code might be :-
c->~_container();
Then free(), but I don't think it is needed in this case, because CONTAINER is not on a heap.
( I have never used malloc, so I am not sure about this part. )
Edit:
My solution is a quick patch to solve a single problem. (not print "Destroyed")
Please also read Michael Anderson's solution.
It addresses another underlying issue of the OP's code. (malloc)
Edit2:
Here is a good link about placement new that Michael Anderson mentioned.
The code below is copied from the link (with little modification):-
int main(int argc, char* argv[]){
const int NUMELEMENTS=20;
char *pBuffer = new char[NUMELEMENTS*sizeof(A)];
//^^^ difference : your "CONTAINER" could be char[xxxx] (without new)
A *pA = (A*)pBuffer;
for(int i = 0; i < NUMELEMENTS; ++i) {
pA[i] = new (pA + i) A();
}
printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);
// dont forget to destroy!
for(int i = 0; i < NUMELEMENTS; ++i){
pA[i].~A();
}
delete[] pBuffer;//<--- no need to delete char[] if it is a stack variable
return 0;
}
For further detail, please see that above link (because I don't want to copy more of it to here).
Here is another useful link : Using malloc in C++ is generally not recommended.

Related

C++ why does new keyword works and malloc does not?

I'm learning about pointers and structures and I ran into this hard to understand the problem for me.
I have created this simple program for testing purpose:
#include <iostream>
struct testStructure
{
int a = 0;
int b = 0;
int c = 400;
};
int main()
{
struct testStructure* testStruct;
testStruct = new testSctructure;
std::cout << testStruct->c;
delete testStruct;
return 0;
}
the above program works just fine, it prints the value 400. But when i try to do it with malloc:
#include <iostream>
struct testStructure
{
int a = 0;
int b = 0;
int c = 400;
};
int main()
{
struct testStructure* testStruct;
testStruct = (testStructure*)malloc(sizeof testStructure);
std::cout << testStruct->c;
free(testStruct);
return 0;
}
it gives me this value:
-842150451
Why?
The above examples were written and build in Visual Studio 2019.
I know that in C++ you should almost always want to use new keyword but I wanted to experiment a bit.
new initializes the allocated memory with the class' constructor (which is implicit in this this case).
malloc performs no initialization, it just allocates a portion of memory. Reading uninitiazlied memory will have undefined behavior.
Here's how your second example can be made to work. In general, this is not a recommended way of working with C++, but there are some valid use cases.
#include <cstdlib>
#include <iostream>
struct testStructure {
int a = 0;
int b = 0;
int c = 400;
};
int main() {
auto testStruct_memory = std::malloc(sizeof(testStructure));
// In-place constructor.
auto testStruct = new(testStruct_memory) testStructure();
std::cout << testStruct->c << "\n";
// In-place destructor.
testStruct->~testStructure();
std::free(testStruct_memory);
}
In the case of malloc, you allocated a block of memory, but did not create an object. The testStructure constructor was not called.
You could call the constructor on the memory area with a placement new:
char* ptr = malloc(sizeof testStructure);
testStruct = new(ptr) testStructure;
but this is hard to read, confusing, hard to maintain, and fraught with risk. For example, you need
to free() not delete ptr
you need to similarly explicitly call the destructor.
So, not recommended.

Triggered a breakpoint (Destructor) with class template type is a version of itself?

With a class like this:
template <class Type>
class test {
Type* ptr;
public:
test() {
ptr = new Type;
}
test(int x) {
ptr = new int;
*ptr = x;
}
test(const test<Type>& other) {
ptr = new Type;
*ptr = *other.ptr;
}
~test() {
delete ptr;
cout << "Deleted " << typeid(test<Type>).name() << endl;
}
Type& getptr () {
return *ptr;
}
};
And use it:
int main() {
test<int> a = 5; // This seems to be fine
test<int> c = a; // This seems to be fine
test<test<int>> b;
b.getptr() = a; // This seems fine to me
cout << b.getptr().getptr() << endl; // This worked (Printed 5)
return 0;
}
Then a breakpoint is triggered at the line
delete ptr;
When I delete the line (Cause I know it causing the error but I dont know why)
b.getptr() = a;
or change it to
b.getptr().getptr() = 5;
everything work.
So why does a breakpoint is triggered when I use
b.getptr() = a;
but
test<int> c = a;
b.getptr().getptr() = 5;
both worked? Isn't they're the same as "b.getptr()" return a reference to *(b.ptr) which is the same to the line above and they're all have the same type "test"? (I tested this too)
cout << typeid(b.getptr()).name() << endl; // Print "class test<int>"
And also, with
b.getptr() = a;
it's still print the correct output.
Can someone explain what am I doing wrong or missing? I've tried searching for answer myself but I can't still neither understand what's wrong nor found a way to fix it.
Thank you.
Sorry for my terrible English, also because of that I can't find a better way to describe my question better in the title.
After the instruction
b.getptr() = a;
both a and b contain a pointer to the same allocated value.
This is because b.getptr() return a reference to the managed (*ptr), that is a test<int>, and copying in it a you copy the ptr in a in (*ptr).ptr.
So, at the end of main(), you delete two times the same allocated memory: crash!
Well... the crash isn't guaranteed (you have an undefined behavior) but often you have a crash. (thanks to Algirdas Preidžius that pointed it)
When you directly manage allocated memory, you need copy constructors and you need to define an operator=() to avoid this sort of problem.
Starting from C++11, you also need a move constructor and an operator=() that receive a right reference.

Releasing memory in a function

I was about to ask a rather simple beginner question the other day about a c++ function I was working on when I realized I hadn't released the memory for my function. That never seems to end well around here.
It seems like this would be a common question but I wasn't able to find anything at my level of understanding in c++
How would I properly free memory in this code
#include <iostream>
class thing{
public:
int a;
};
thing makeThing(){
thing *t = new thing;
t -> a = 5;
return *t;
}
int main(){
thing thing1 = makeThing();
std::cout << "a: " << thing1.a << std::endl;
return 0;
}
As far as I know I'm not able to free it after the function terminates.
I tried this:
delete &thing1;
but based on the core dump, I assume that’s not the way to do it.
Since you return by value, that means you return a copy of the object. The original object, created by new things, can't be reached after the function returns (not reliably anyway).
You can return a pointer:
thing* makeThing(){
thing *t = new thing;
t -> a = 5;
return t;
}
And delete that.
But you should really just return an object, and not even allocate anything with new in this case.
Sometimes the simplest way to free memory is to not have allocated it to begin with:
thing makeThing(){
thing t;
t.a = 5;
return t;
}
The reason what you're trying to do doesn't work is that when you have:
delete &thing1;
that's the address of your local object... that's not the address of what you actually allocated. That one got copied into yours, and now you have no way to access it.
If you wanted to allocate your thing, you would need to return the pointer directly. Preferably, wrapped somehow:
std::unique_ptr<thing> makeThing() {
std::unique_ptr<thing> t(new thing);
t->a = 5;
return t;
}
thing makeThing(){
thing *t = new thing;
t -> a = 5;
return *t;
}
Leads to an immediate memory leak. The t variable will go out of scope after makeThing() returns, and the allocated memory will never be released or accessible for release with an appropriate delete statement.
There's a copy of the newly created t returned.
To fix it just create a local variable and retun a copy:
thing makeThing(){
thing t;
t.a = 5;
return t;
}
If you really want to use new this is the right way to do it. This code is C++11, so you may need to turn on some option if that is not already the default in the compiler you are using. I habitually use C++11, since the improvements in that version of the language are really worthwhile.
#include <iostream>
#include <memory>
#include <ostream>
class thing {
public:
int a;
};
std::ostream& operator<<(std::ostream& os, const thing& t) {
os << t.a;
return os;
}
std::unique_ptr<thing> makeThing() {
std::unique_ptr<thing> t(new thing);
t->a = 5;
return std::move(t);
}
int main() {
auto thing1 = makeThing();
std::cout << "a: " << *thing1 << std::endl;
return 0;
}
But really if all you want to do is create an object there is no need to allocate it on the heap. You can just do it like the code below. Notice that the object is created without the use of new. The object is copied when it is returned from makeThing(), and the compiler uses the default copy constructor for class thing (which I did not replace) when doing that.
#include <iostream>
#include <ostream>
thing makeThing() {
thing t;
t.a = 5;
return t;
}
int main() {
auto thing1 = makeThing();
std::cout << "a: " << thing1 << std::endl;
return 0;
}
The ostream inserter does not need to change, so I omitted it. Same for the class definition.

Using static object in overloaded global new operator cause core dumped run time error

In this code I tired to simply know which object I forget to delete so I made a singleton with one static object to count the new allocated objects, but using this object inside global new function causes error, the same error occurs if I want to use standard objects like cout. What could be the cause of that error and what is the proper way to get the same effect?
#include <vector>
#include <cstdlib>
#include <new>
#include <iostream>
class Count_new { //singleton
std::vector<void*>count_v ; // to get "new" pointers
Count_new(){}
Count_new(const Count_new&);
public:
void count(void * m) {
count_v.push_back(m);
}
static Count_new * instance(){
static Count_new c ;
return &c;
}
~Count_new()
{
unsigned int index = 0 ;
while (index < count_v.size()) {
if(count_v.at(index) != NULL)
std::cout << count_v.at(index) << " not deleted\n" ;
}
}
};
Count_new &c = *Count_new::instance();
void * operator new (size_t sz) throw (std::bad_alloc){
void *m = malloc(sz);
c.count(m); //produce Error core dumped
return m;
}
class Obj{};
int main() {
try {
Obj *p1 = new Obj ;
Obj *p2 = new Obj ;
}catch(std::bad_alloc&b){
std::cout << "Error in memory allocation:" << b.what()<< "\n";
}
}
The problem is you're hitting endless recursion. You've replaced the global ::operator new which is used by everything by default. This includes the allocation performed by the default allocators, such as the one std::vector<T> uses. So your call to count calls push_back, which needs to reallocate, which eventually calls ::operator new, which calls count, which ...
If you want to keep this scheme, you'll have to write allocator which doesn't use ::operator new, and then modify the type of count_v to use that allocator.
Oh and I'd drop the dynamic exception specification, they're deprecated since C++11.

Detecting stack or heap allocation

I have a class I’d like to be able to set a flag in that says if it is heap allocated so it can properly clean up after itself and not try to delete itself if it’s on the stack. The problem is...I can’t seem to override both new and the constructors at the same time. So it goes from my new overload that sets the isHeapAllocated flag and then into my constructor which resets the flag.
void* String8::operator new(size_t size)
{
String8* string = (String8*)malloc(size);
if(string == null)
Exception("allocation fail : no free memory");
string->isHeapAllocated = true;
return string;
}
String8::String8()
{
isHeapAllocated = false;
}
So new String8() sets the isHeapAllocated flag and then resets it to false. Is there any way to do this?
It will not work as intended:
The new operator return unitialized memory to be given to the constructor.
You -correctly- do String8* string = (String8*)malloc(size);, but *string, at this stage is not yet a String8 object: it is just the memory bulk that will contain it.
So string->isHeapAllocated = true; in fact sets a flag inside a not yet constructed object (that's UB).
Admitting this will not compromise the OS process, so that the program will not crash (you write memory that belongs already to you, after all ...), when you will later do something like String8* ptr = new String8;, after new returns, the String8::String8 constructor is called, and the member will be set back to "false" independently on what you did in the new operator overload.
The idiomatic way to manage C++ objects is let who allocate to be responsible to deallocate.
(and if "who" it is the stack, it just do that by definition).
This is a bad idea, but here’s a way to do it that doesn’t invoke undefined behaviour.
#include <iostream>
#include <memory>
#include <set>
using namespace std;
class C {
public:
void* operator new(size_t size) {
C* c = static_cast<C*>(::operator new(size));
heap_instances.insert(c);
return c;
}
C() : heap_allocated(heap_instances.find(this) != heap_instances.end()) {}
const bool heap_allocated;
private:
static set<const C*> heap_instances;
};
set<const C*> C::heap_instances;
int main(int argc, char** argv) {
cout << boolalpha;
C stack;
cout << stack.heap_allocated << '\n'; // false
C* heap_nozero = new C;
cout << heap_nozero->heap_allocated << '\n'; // true
delete heap_nozero;
C* heap_zero = new C();
cout << heap_zero->heap_allocated << '\n'; // true
delete heap_zero;
}
You can remove pointers from heap_instances when you’re done with them, of course, and use a more suitable container if you’re running in a multithreaded environment. But again, I wouldn’t recommend that you actually do this—deciding behaviour based on allocation is not something an object ought to do.
The only legitimate reason I can think of for this is to enable delete this. While that’s safe if you’re careful not to access members after the object’s suicide, it’s usually saner to let objects manage the lifetimes of other objects.
Note that the construtor gets called if it is allocated on the stack or the heap and there is no way for the object to detect if it was allocated on the stack or in the heap.
To create an object at the stack you don't use any memory allocation functions like this
String8 myString;
To create it on the heap you do
String8 *myString = new String8();
note that you do have to do the cleanup manually after not using the object anymore.
For the use of Heap objects bound to stack scope you can check out the RAII principle which is used intensly by c++ programs (see here for a better explaination of the difference of heap allocation and stack allocation).
Not sure why you need this, really. It's caller's responsibility to call delete if needed and your class's destructor should not be different whether it's called on the object on stack or on the heap... But, maybe, you are doing some special purpose class... Here is my quick take on it.
EDIT: You should also, probably, add custom delete operator to your class, unless you know that global delete calls a deallocation function that matches the allocation function you use in your custom new operator.
#include <cstdlib>
#include <iostream>
namespace so
{
class _test_
{
private:
static bool flag_allocation_heap;
bool flag_heap;
public:
_test_()
: flag_heap( flag_allocation_heap )
{
flag_allocation_heap = 0;
std::cout << flag_heap << std::endl;
}
void * operator new( std::size_t _size )
{
_test_ * test_ = static_cast< _test_ * >( std::malloc( _size ) );
flag_allocation_heap = 1;
return ( test_ );
}
};
bool _test_::flag_allocation_heap = 0;
} // namespace so
int main()
{
so::_test_ test_stack_;
so::_test_ * test_memory_ = new so::_test_;
delete test_memory_;
return( 0 );
}
Output:
0
1