How do I allocate a delegate on the heap? - d

How do I heap allocate a delegate and get a pointer to it?
I want to be able to cast it to a void pointer and back, so I can store it in a heterogeneous array.

a delegate in D, similar to a dynamic array, is a simple struct with 2 pointer fields. It has the fields:
.ptr which is the context pointer (this reference, closure, stack frame pointer)
.funcptr which is the function pointer
So, if you can absolutely make sure the context pointer won't be destroyed when you call your serialized delegate (best on a class this reference, meaning most commonly a member function of a class), you can just store a struct on the heap with these 2 void* values or make a copy of its bytes and then afterwards deserialize it back to a delegate.
Example:
alias MyDelegate = void delegate();
void main()
{
int local;
MyDelegate dlg = () { import std.stdio; writeln("delegate ", local); };
// T.sizeof gives the size of a variable on the stack, so we get the size
// of the delegate summing together context pointer and function pointer
// (and potentially additional ABI things depending on the compiler/target)
// `.dup` copies the bytes from the stack stored for the delegate to the
// heap, but it doesn't pin the context pointer or anything similar which
// would however make this a safer operation.
auto heap = (cast(ubyte*)&dlg)[0 .. MyDelegate.sizeof].dup.ptr;
local = 5;
callHeapDlg(heap);
}
void callHeapDlg(ubyte* heap)
{
// This could be a potentially unsafe cast if casting to some other delegate!
// You might be casting away safety attributes or other things. Best to
// restrict the type of the delegate you convert to heap from the start.
// Simply recreates the delegate by casting a pointer to the bytes you have
// copied to a pointer to a delegate object and then dereferencing it.
// This copies the pointers from the heap back to the stack here.
auto dlg = *(cast(MyDelegate*) heap);
dlg(); // prints "delegate 5"
}
Try it online
But never forget that this is an unsafe operation which you could potentially corrupt your application with and even accidentally introduce arbitrary code execution. Especially if your delegate context pointer goes out of scope and gets deallocated you can get major undebugable problems.
In this case for example you shouldn't call the heap allocated delegate outside the main function because it most likely contains a pointer to the current stack frame of the main function which gets invalid after leaving it.
See https://dlang.org/spec/abi.html#delegates

Related

Convert unique_ptr to void* and back, do I need to free?

In my code I use a library that has a function store_pointer accepting a void* and saving it in memory. There is then another function retrieve_pointer() that returns this void * to me, I don't have control over this library so I can't change how the function behaves.
Now I need to pass a variable to this function and get the pointer back, I have the code set up as follows:
struct Task
{
int mId;
Task(int id ) :mId(id)
{
std::cout<<"Task::Constructor"<<std::endl;
}
~Task()
{
std::cout<<"Task::Destructor"<<std::endl;
}
};
std::unique_ptr<Task> taskPtr(new Task(23));
store_pointer(&taskPtr);
// do stuff that doesn't involve taskPtr
Task *new_taskPtr = reinterpret_cast<Task *>(retrieve_pointer());
// do stuff with new_taskPtr pointer
Right now this all works but I wonder if the *new_taskPtr pointer needs to be deleted or if the reinterpret_cast "restores" the pointer to a unique_ptr and so the memory will be deleted automatically when it goes out of scope/the program ends.
std::unique_ptr<Task> taskPtr(new Task(23));
When this variable goes out of scope, the dynamic allocation will be deleted. There is no need to, and you mustn't delete it yourself unless you call release on the unique pointer, which is the only way to transfer the ownership out of a unique pointer (besides transferring ownership to another unique pointer).
Any casts that you may do have no effect on this.
You are storing a reference to unique_ptr:
store_pointer(&taskPtr);
As long as you don’t move the taskPtr or don’t mess with its internal pointer you are safe and don’t need delete.
Note that if taskPtr goes out of scope earlier than the user you will have dangling reference.

object created in function, is it saved on stack or on heap?

I am using c++ specifically:
when I create an object in a function, will this object be saved on the stack or on the heap?
reason I am asking is since I need to save a pointer to an object, and the only place the object can be created is within functions, so if I have a pointer to that object and the method finishes, the pointer might be pointing to garbage after.
--> if I add a pointer to the object to a list (which is a member of the class) and then the method finishes I might have the element in the list pointing to garbage.
so again - when the object is created in a method, is it saved on the stack (where it will be irrelevant after the function ends) or is it saved on the heap (therefore I can point to it without causing any issues..)?
example:
class blah{
private:
list<*blee> b;
public:
void addBlee() {
blee b;
blee* bp = &b;
list.push_front(bp);
}
}
you can ignore syntax issues -- the above is just to understand the concept and dilemma...
Thanks all!
Keep in mind following thing: the object is NEVER created in the heap (more correctly called 'dynamic storage' in C++) unless explicitly allocated on the heap using new operator or malloc variant.
Everything else is either stack/register (which in C++ should be called 'automatic storage') or a a statically allocated variable. An example of statically allocated variables are global variables in your program, variables local to the function which are declared static or static data members of classess.
You also need to very clear disntguish between a pointer and the object itself. In the following single line:
void foo() {
int* i = new int(42);
}
int is allocated dynamically (on the heap), while pointer to that allocated int has an automatic storage (stack or register). As a result, once foo() exits, the pointer is obliterated, but the dynamically allocated object remains without any means to access it. This is called classic memory leak.
Heap is the segment where dynamic memory allocation usually takes place so when ever you explicitly allocate memory to anything in a program you have given it memory from the heap segment.
Obj yo = new Obj; //something like this.
Stack is the another segment where automatic variables are stored, along with information that is saved each time a function is called.
Like when we declare:
*int* variable;
It will be on the stack and its validity is only till a particular function exits, whereas variables, objects etc on the heap remain there till main() finishes.
void addBlee() {
blee b; // this is created on the stack
blee* bp = &b;
list.push_front(bp); // this is a pointer to that object
} // after this brace b no longer exists, hence you have a dangling pointer
Do this instead:
list.push_front(new blee); // this is created on the heap and
// therefore it's lifetime is until you call
// delete on it`

C++ Lambdas: captured pointer to STL container changing address after pop?

I'm trying to figure out why the following code breaks. After objects->pop(); is called in the lambda expression, the memory address of objects changes to 0xfeeefeee when debugging in Visual Studio. I can get around this issue by doing auto p = objects; before the pop, and then using p instead of objects in the second line of the lambda. However, I must be missing something fundamental here.
class Obj
{
public:
Obj(stack<shared_ptr<Obj>>* const objects) {
fun = [=] {
objects->pop(); // objects' address changed after this executes
objects->push(shared_ptr<Obj>(new Obj(objects)));
};
}
function<void(void)> fun;
};
int main()
{
stack<shared_ptr<Obj>> objects;
objects.push(shared_ptr<Obj>(new Obj(&objects)));
objects.top().get()->fun();
return 0;
}
What you are observing is undefined behavior.
The memory that the captured objects variable occupies is freed when you call objects->pop(); A good hint for this is the value it changes to: 0xFEEEFEEE. This magic number indicates freed memory.
Let's analyse what happens.
stack<shared_ptr<Obj>> objects;
objects.push(shared_ptr<Obj>(new Obj(&objects)));
A stack with shared_ptr's is created. Pushed on top of it is a new Obj instance, whose constructor argument is a pointer to our stack.
Obj(stack<shared_ptr<Obj>>* const objects) {
fun = [=] {
/* ... */
};
}
A function object is assigned a lambda, which captures the objects argument.
objects.top().get()->fun(); calls the function object:
objects->pop(); // objects' address changed after this executes
The top element of the stack that objects points to, is the Obj instance to which the fun object belongs. By popping it off, the only (and therefore last) instance of the shared_ptr holding a reference to it goes out of scope and frees the memory that it used. This includes the captured pointer to objects. In a debug build HeapFree sets it to 0xFEEEFEEE. In a release build anything could happen. After this point you're referencing released memory, which is undefined behavior.
When you call objeccts->pop(), the shared_ptr on top of the stack is destroyed. It is the last pointer to your instance of Obj, so that instance is destroyed. That instance contains the function object fun, so the function object is also destroyed.
Any access to the captured variables of the function object after this point is undefined behaviour, which first happens right on the next line.
For what I could deduce debugging your code, it seems to me that eventually you are doing pop on the top of stack, and with that you are trying to delete the pointer to the objects (the variable in the main function: by the way, you should rename that to eliminate confusion). As it is not on the heap, UB kicks in, and it gives (me) a segmentation fault.

What is the preferred way to instantiate in C++?

I am still new to C++. I have found that you can instantiate an instance in C++ with two different ways:
// First way
Foo foo;
foo.do_something();
// Second way
Baz *baz = new Baz();
baz->do_something();
And with both I don't see big difference and can access the attributes. Which is the preferred way in C++? Or if the question is not relevant, when do we use which and what is the difference between the two?
Thank you for your help.
The question is not relevant: there's no preferred way, those just do different things.
C++ both has value and reference semantics. When a function asks for a value, it means you'll pass it a copy of your whole object. When it asks for a reference (or a pointer), you'll only pass it the memory address of that object. Both semantics are convertible, that is, if you get a value, you can get a reference or a pointer to it and then use it, and when you get a reference you can get its value and use it. Take this example:
void foo(int bar) { bar = 4; }
void foo(int* bar) { *bar = 4; }
void test()
{
int someNumber = 3;
foo(someNumber); // calls foo(int)
std::cout << someNumber << std::endl;
// printed 3: someNumber was not modified because of value semantics,
// as we passed a copy of someNumber to foo, changes were not repercuted
// to our local version
foo(&someNumber); // calls foo(int*)
std::cout << someNumber << std::endl;
// printed 4: someNumber was modified, because passing a pointer lets people
// change the pointed value
}
It is a very, very common thing to create a reference to a value (i.e. get the pointer of a value), because references are very useful, especially for complex types, where passing a reference notably avoids a possibly costly copy operation.
Now, the instantiation way you'll use depends on what you want to achieve. The first way you've shown uses automatic storage; the second uses the heap.
The main difference is that objects on automatic storage are destroyed with the scope in which they existed (a scope being roughly defined as a pair of matching curly braces). This means that you must not ever return a reference to an object allocated on automatic storage from a regular function, because by the time your function returns, the object will have been destroyed and its memory space may be reused for anything at any later point by your program. (There are also performance benefits for objects allocated on automatic storage because your OS doesn't have to look up a place where it might put your new object.)
Objects on the heap, on the other hand, continue to exist until they are explicitly deleted by a delete statement. There is an OS- and platform-dependant performance overhead to this, since your OS needs to look up your program's memory to find a large enough unoccupied place to create your object at. Since C++ is not garbage-collected, you must instruct your program when it is the time to delete an object on the heap. Failure to do so leads to leaks: objects on the heap that are no longer referenced by any variable, but were not explicitly deleted and therefore will exist until your program exits.
So it's a matter of tradeoff. Either you accept that your values can't outlive your functions, or you accept that you must explicitly delete it yourself at some point. Other than that, both ways of allocating objects are valid and work as expected.
For further reference, automatic storage means that the object is allocated wherever its parent scope was. For instance, if you have a class Foo that contains a std::string, the std::string will exist wherever you allocate your Foo object.
class Foo
{
public:
// in this context, automatic storage refers to wherever Foo will be allocated
std::string a;
};
int foo()
{
// in this context, automatic storage refers to your program's stack
Foo bar; // 'bar' is on the stack, so 'a' is on the stack
Foo* baz = new Foo; // 'baz' is on the heap, so 'a' is on the heap too
// but still, in both cases 'a' will be deleted once the holding object
// is destroyed
}
As stated above, you cannot directly leak objects that reside on automatic storage, but you cannot use them once the scope in which they were created is destroyed. For instance:
int* foo()
{
int a; // cannot be leaked: automatically managed by the function scope
return &a; // BAD: a doesn't exist anymore
}
int* foo()
{
int* a = new int; // can be leaked
return a; // NOT AS BAD: now the pointer points to somewhere valid,
// but you eventually need to call `delete a` to release the memory
}
The first way -- "allocating on the stack" -- is generally faster and preferred much of the time. The constructed object is destroyed when the function returns. This is both a blessing -- no memory leaks! -- and a curse, because you can't create an object that lives for a longer time.
The second way -- "allocating on the heap" is slower, and you have to manually delete the objects at some point. But it has the advantage that the objects can live on until you delete them.
The first way allocates the object on the stack (though the class itself may have heap-allocated members). The second way allocates the object on the heap, and must be explicitly delete'd later.
It's not like in languages like Java or C# where objects are always heap-allocated.
They do very different things. The first one allocates an object on the stack, the 2nd on the heap. The stack allocation only lasts for the lifetime of the declaring method; the heap allocation lasts until you delete the object.
The second way is the only way to dynamically allocate objects, but comes with the added complexity that you must remember to return that memory to the operating system (via delete/delete[]) when you are done with it.
The first way will create the object on the stack, and the object will go away when you return from the function it was created in.
The second way will create the object on the heap, and the object will stick around until you call delete foo;.
If the object is just a temporary variable, the first way is better. If it's more permanent data, the second way is better - just remember to call delete when you're finally done with it so you don't build up cruft on your heap.
Hope this helps!

Stack memory allocation and deallocation mechanism

If I pass by value as an argument to a particular function, then will that function deallocate memory of this parameter when the function execution ends?
If I pass a pointer or reference as argument, what happens if function deallocates memory of the pointer argument? Will it affect to the variable outside of function?
In the first case memory will be "deallocated" (actually stack pointer will be increased). If this is not POD type variable destructor is called, so the memory will be deallocated from heap if it was allocated there.
In the second case value referenced by pointer won't be deallocated - only memory for pointer will be deallocated.
For point 1, it depends on the type of argument. Passing e.g. a 'string' by value will do an implicit copy, and the memory that copy uses will be deallocated when the variable (function parameter) goes out of scope. This won't automatically happen for your own types - you'll need to set up construction and destruction properly.
For the second - yeah, deallocating using a pointer will affect the memory it addresses - both inside the function and outside.
To clarify the second point:
void func(char *someMemory) {
delete[] someMemory;
}
//...
char *myArray = new char[100];
func(myArray);
...will delete the allocated memory - using myArray after the call to func is BAD.
If you pass a value or a pointer on the stack the memory required to hold that value is allocated on the stack...
The way the stack works you can keep "allocating" more memory but it has to be "freed" in reverse order.
So:
void f(int *ptr, int v)
{
// Do something
}
When you call f() the value of ptr and v are "pushed" on the stack, that is enough memory is magically created to hold those values. When the function returns the stack is adjusted the other way, in a sense they are "popped" from the stack.
This pushing and popping has no effect on the original pointer or value. So:
ptr++;
Will not effect the value of the pointer held by the calling function.
If you dereference, *ptr, the pointer you are accessing the same data that is visible from outside the function. If you free() the pointer this impacts what is seen from outside the function. So when you pass a pointer there are no copies made of the original data the pointer is pointing to but there is a copy made of the actual pointer. The pointer is passed by value.