I am not gonna pretend I am very experienced with lambdas, but with this seemingly simple issue, I think I need deeper insight on how it actually works.
I am instantiating an object on an outer scope, and using 2 lambdas, I attempt to modify that pointer.
// Object to be manipulated
Object* obj= nullptr;
// To be invoked externally in order to construct and initialize obj
std::function<void(std::function<void(const String&)>)> SetObject
= [&obj](std::function<void(const String&)> func)
{
obj= new Object();
// ... Initialize Values
};
// To be invoked externally to reset and delete obj
std::function<void()> ResetObject
= [&obj]()
{
if(obj)
{
delete obj;
obj= nullptr;
}
};
A main code executes and first calls the RESET method before creating a new instance of Object. Assume the "main" code has no way of accessing, reading, or modifying obj - hence the reliance on a blind reset.
Expected Result: The first time the reset expression is invoked, the check on obj should return false because obj was set to nullptr in the outer scope -- nothing happens.
Actual Result: By the time reset is executed, obj no longer points to NULL, the check returns true and delete is called, causing an access violation.
I would like to know if the whatever I am attempting to do is an invalid operation to begin with, or whether the way I am capturing my variables is incorrect. I tried capturing the pointer by value, setting the function to mutable, and a combination of reference and value capture out of desperation.
EDIT: At this point, I believe the scope of the object is the main culprit as pointed out by others. I will attempt a workaround with
that in mind and report back.
While we cannot tell from your example alone, I suspect obj is perhaps a local variable which goes out of scope after being captured. One way to solve this would be to add another level of indirection:
Object** objptr = new Object*();
std::function<void(std::function<void(const String&)>)> SetObject
= [objptr](std::function<void(const String&)> func)
{
*objptr = new Object();
};
std::function<void()> ResetObject
= [objptr]() // Note we are now capturing objptr by value
{
if(*objptr)
{
delete *objptr;
*objptr = nullptr;
}
// Is objptr reused by another call to SetObject?
// If not, delete it here as well.
// delete objptr;
};
Related
I want to allocate an object of type custom_type_t (operator= is not available for this custom_type_t and I'm unable to modify that part of the codebase) depending on whether a condition is met and, if it's not met, that object should not be created at all.
I was initially thinking I could do:
// create the object even if it's not needed
custom_type_t object; // just use their default constructor which hopefully isn't expensive
if (condition_met) {
object = custom_type_t(constructor arguments);
}
However, this isn't possible because there's no operator=.
I'm wondering if there's a way in which I can do something like the following:
int* custom_type_t ptr;
if (condition_met) {
custom_type_t object = custom_type_t(constructor arguments);
ptr = &custom_type_t;
} // but object may go out of scope here, so ptr may end up pointing to garbage
// ptr will be used later on if condition_met == true
But I need to have object actually remain valid so ptr doesn't point to garbage?
Your problems/confusion seem to lie in separating the idea of creating an object from that of explicitly declaring that object. You can quite easily (conditionally) create your object, and subsequently use it, by just declaring a pointer to it.
Using a simple 'raw' pointer, something like this (for the sake of the example, I have assumed that two int values are required for the constructor arguments):
void function()
{
custom_type_t* pObject = nullptr;
if (condition_met) {
pObject = new custom_type_t(42, -9);
}
// ...
delete pObject; // If still nullptr, no problem - does nothing.
}
Or, better, using a smart pointer:
void function()
{
std::unique_ptr<custom_type_t> pObject;
if (condition_met) {
pObject = std::make_unique<custom_type_t>(42, -9);
}
//...
// "pObject" is automagically freed when this function returns.
}
In either of the above cases, you can use *pObject in expressions where you would otherwise use object, and you can use pObject->memberFunc() instead of object.memberFunc().
I have function in c++ with 2 optional c'tor of an object I've built (one with something in vector "vals" and other without).
...
RecievedMessage a(sc, type);
if (!vals.empty()){
//a.~RecievedMessage();
RecievedMessage a(sc, type, vals);
}
return &a;
}
the line in // is optional.
Would it work (with or without the optional line)? Why? If no, how to fix it without setter for "vals"?
thanks a lot.
No, it wouldn't work.
RecievedMessage a(sc, type);
// Here we construct 'a'
if (!vals.empty()){
//a.~RecievedMessage();
// If we enable this line, we destroy 'a'
RecievedMessage a(sc, type, vals);
// Here we construct a second 'a' that only exists in this block
}
// End of block: The inner 'a' is destroyed here automatically
return &a;
}
// End of block: The outer 'a' is destroyed here, again.
Destroying an object twice has undefined behavior. You don't want that.
If you don't call the destructor manually, the outer a is only destroyed once, which is good.
But in either case, RecievedMessage a(sc, type, vals); has nothing to do with the outer a and merely creates another variable.
There would be ways to work around that, but the final line of your code makes it all pointless:
return &a;
You're returning the address of a local variable. This is broken in and of itself: When the function returns, all of its local variables are destroyed automatically, so what you're returning is an invalid pointer.
Your code is all over the place, but what I think you're looking for is something like this:
ReceivedMessage *MakeReceivedMessage (foo sc, bar type, vector<whatever>& vals)
{
if (vals.empty())
return new ReceivedMessage (sc, type);
return new ReceivedMessage (sc, type, vals);
}
Of course, it would be better in this example to just have a single constructor and have the object test whether vals is empty when appropriate, but, in general, you can call whatever constructor you like whenever you like. Just manage your object lifetimes properly (and don't - ever - return a pointer to an object on the stack).
Example usage (to manage the lifetime of the object returned properly):
std::unique_ptr<ReceivedMessage> MyReceivedMessage (MakeReceivedMessage (...));
MyReceivedMessage->DoFunkyStuffWithMessage ();
....
Or, as melpomene points out, you can return a std::unique_ptr<ReceivedMessage> in the first place. Some (many?) would prefer that. You can construct it with std::make_unique.
There are three main issues with your code right now:
First of all, your commented out call to the destructor ~ReceivedMessage() should not be there at all. In C++, the destructor of objects is automatically called when an object's lifetime ends (either when it goes out of scope, or when delete is called if it was dynamically allocated with new). While there are some situations where explicitly calling a destructor is necessary ("placement new" for example), these are situations you're very unlikely to come across.
Secondly, your RecievedMessage a(sc, type, vals); declaration in the inner if does not replace the value of a in the outer scope. This just creates another variable of the same name which shadows the outer a, while return &a; in the outer scope can only refer to the outer a. The inner a no longer exists at this point as it has gone out of scope.
A way to fix this issue is to instead assign a new value to a by using the = operator and constructing a temporary ReceivedMessage:
if (!vals.empty()) {
a = ReceivedMessage(sc, type, vals);
}
This should work as long as a correct operator= is defined (implicitly or otherwise) for ReceivedMessage.
Thirdly, your function is returning a pointer to the local variable a. Since objects in C++ are destroyed as soon as they go out of scope, a no longer exists by the time the function has returned, so the ReceivedMessage * pointer the calling code obtains is invalid and it would be undefined behaviour to dereference that pointer and make use of it.
There are a couple of fixes to this issue:
The first option is instead of returning a pointer (ReceivedMessage *), just return a ReceivedMessage by value.
ReceivedMessage foo()
{
ReceivedMessage a(123);
return a;
}
This should work as long as a correct copy or move constructor is defined (implicitly or otherwise) for ReceivedMessage.
The second option is to make use of std::unique_ptr, and make your function instead return std::unique_ptr<ReceivedMessage>.
#include <memory>
std::unique_ptr<ReceivedMessage> foo()
{
std::unique_ptr<ReceivedMessage> a;
if (vals.empty()) {
a = std::make_unique<ReceivedMessage>(sc, type);
} else {
a = std::make_unique<ReceivedMessage>(sc, type, vals);
}
return a;
}
The advantage to this approach is that unique_ptr is nullable, so you can create a null unique_ptr without having to construct a ReceivedMessage straight away. Additionally, you can move and assign unique_ptr values safely without having a correct operator= or a correct copy / move constructor defined.
The calling code may look like this, when using unique_ptr:
std::unique_ptr<ReceivedMessage> message = foo();
foo->bar();
as opposed to the following when using ReceivedMessage directly:
ReceivedMessage message = foo();
foo.bar();
Is it possible to avoid the GC for delegates?
I am building a task system. I have N-Threads with a local task queue. A task queue is basically just a Array!Fiber tasks. Because it is discouraged to send fibers to a different thread, I am sending a closure/delegate to a thread, create the fiber from that delegate and put it in the array tasks.
Now the delegates that I am sending are delegates that capture variables.
//Some Pseudo code
auto f = //some function;
auto cell = Cell(...);
auto del = () {
let res = f();
cell.write(res);
}
send(del);
}
Now cell is heap allocated and synchronized with an atomic counter. I can then check if the atomic counter from cell has reached 0, if it did I can safely read from it.
The problem is that delegates which capture variables, allocate the variables on the GC. Now I only allocate a pointer and it is probably not a huge problem but I would still like to avoid the GC.
How would I do this?
You might already know all this, but this is a bit of a FAQ so I'm going to write a few details.
First, let's understand what a delegate is. Like how a slice is just a C data pointer paired with a length, a delegate is just a C data pointer paired with a function pointer. These are passed together to functions expecting them, as if it was defined
struct d_delegate {
void* ptr; // yes, it is actually typed void*!
T* funcptr; // this is actually a function pointer
};
(Note that the fact that there is just one data ptr in there is the reason behind some compiler errors when you try to take a nested delegate inside a class method!)
That void* is what points to the data and like with a slice, it can come from a variety of places:
Object obj = new Object();
string delegate() dg = &obj.toString;
At this point, dg.ptr points to obj, which happens to be a garbage collected class object, but only because I newed it above.
struct MyStruct {
string doSomething() { return "hi"; }
}
MyStruct obj;
string delegate() dg = &obj.doSomething;
In this case, obj lives on the stack due to how I allocated it above, so the dg.ptr also points to that temporary object.
Whether something is a delegate or not says nothing about the memory allocation scheme used for it - this is arguably dangerous because a passed delegate to you might point to a temporary object that will disappear before you're finished with it! (That's the main reason why GC is used by the way, to help prevent such use-after-free bugs.)
So, if delegates can come from any object, why are they assumed to be GC so much? Well, the automatically generated closure can copy local variables to a GC segment when the compiler thinks the lifetime of the delegate is longer than the outer function.
void some_function(void delegate() dg);
void foo() {
int a;
void nested() {
a++;
}
some_function(&nested);
}
Here, the compiler will copy the variable a to a GC segment because it assumes some_function will keep a copy of it and wants to prevent use-after-free bugs (which are a pain to debug as it frequently leads to memory corruption!) as well as memory leaks.
However, if you promise the compiler that you'll do it right yourself by using the scope keyword on the delegate definition, it will trust you and leave the locals right where they are:
void some_function(scope void delegate() dg);
Keeping the rest the same, it will no longer allocate a copy. Doing it on the function definition side is the best because then you, as the function author, can ensure you don't actually keep a copy.
On the usage side though, you can also label it scope:
void foo() {
int a;
void nested() {
a++;
}
// this shouldn't allocate either
scope void delegate() dg = &nested;
some_function(&dg);
}
So, the only time memory is automatically allocated by the GC is when local variables are used by a nested function which has its address taken without the scope keyword.
Note that the () => whatever and () { return foo; } syntaxes are just shorthand for a named nested function with its address being automatically taken, so they work the same way as the above. dg = {a++;}; is the same as dg = &nested; above.
Thus, the key takeaway from this for you is that if you want to manually allocate a delegate, you just need to manually allocate an object and make a delegate from one of its methods instead of automatically capturing variables! But, you need to keep track of the lifetime and free it properly. That's the tricky part.
So for your example:
auto del = () {
let res = f();
cell.write(res);
};
you might translate that into:
struct Helper {
T res;
void del() {
cell.write(res);
}
}
Helper* helper = malloc(Helper.sizeof);
helper.res = res; // copy the local explicitly
send(&helper.del);
Then, on the receiving side, don't forget to free(dg.ptr); when you're done so you don't leak it.
Or, better yet, if you can change send to just actually take Helper objects, you don't need to allocate it at all, you can just pass it by value.
It also occurs to me that you could pack some other data in that pointer to pass other data in-place, but that'd be abi hacking and possibly undefined behavior. Try it if you wanna play though :)
I have a program, where I cannot use the standard std::async and threading mechanisms. Instead I have to code the program like so:
void processor( int argument, std::function<void(int)> callback ) {
int blub = 0;
std::shared_ptr<object> objptr = getObject();
// Function is called later.
// All the internal references are bound here!
auto func = [=, &blub]() {
// !This will fail since blub is accessed by reference!
blub *= 2;
// Since objptr is copied by value it works.
// objptr holds the value of getObject().
objptr->addSomething(blub);
// Finally we need to call another callback to return a value
callback(blub);
};
objptr = getAnotherObject();
// Puts func onto a queue and returns immediately.
// func is executed later.
startProcessing(func);
}
I now would like to know whether I am doing it right or what the best way of using lambdas as asynchronous callbacks is.
EDIT: Added expected behavior to the code comments.
See answer/comments for possible solutions for the problem with blub.
The function object will contain a reference to the local variable blub. As in every other situation in the language, this won't make the local variable live after the function ends.
Copies of all the other captured objects will be stored within the function object, since they're captured-by-value. This means there's no issue with them.
If you want it to live after the function ends, you cannot tie its lifetime to the function: you need dynamic storage duration. A std::unique_ptr can be used to to handle the cleanup of such an object, but it gets a bit annoying because you can't "capture-by-move" into a lambda :S
auto blub = make_unique<int>(0); // [1]
std::shared_ptr<object> objptr = getObject();
// use std::bind to store the unique_ptr with the lambda
auto func = std::bind([=](std::unique_ptr<int>& blub) {
*blub *= 2;
objptr->addSomething(*blub);
callback(*blub);
}, std::move(blub)); // move the unique_ptr into the function object
objptr = getAnotherObject();
// func is not copiable because it holds a unique_ptr
startProcessing(std::move(func)); // move it
As an added note, the old deprecated std::auto_ptr would actually work fine here, because if the lambda captures it by value it gets copied and its strange copy semantics are exactly what's needed.
1. See GOTW #102 for make_unique.
I am trying to write a function that will check if an object exists:
bool UnloadingBay::isEmpty() {
bool isEmpty = true;
if(this->unloadingShip != NULL) {
isEmpty = false;
}
return isEmpty;
}
I am pretty new to C++ and not sure if my Java background is confusing something, but the compiler gives an error:
UnloadingBay.cpp:36: error: no match for ‘operator!=’ in ‘((UnloadingBay*)this)->UnloadingBay::unloadingShip != 0’
I can't seem to figure out why it doesn't work.
Here is the declaration for class UnloadingBay:
class UnloadingBay {
private:
Ship unloadingShip;
public:
UnloadingBay();
~UnloadingBay();
void unloadContainer(Container container);
void loadContainer(Container container);
void dockShip(Ship ship);
void undockShip(Ship ship);
bool isEmpty();
};
It sounds like you may need a primer on the concept of a "variable" in C++.
In C++ every variable's lifetime is tied to it's encompassing scope. The simplest example of this is a function's local variables:
void foo() // foo scope begins
{
UnloadingShip anUnloadingShip; // constructed with default constructor
// do stuff without fear!
anUnloadingShip.Unload();
} // // foo scope ends, anything associated with it guaranteed to go away
In the above code "anUnloadingShip" is default constructed when the function foo is entered (ie its scope is entered). No "new" required. When the encompassing scope goes away (in this case when foo exits), your user-defined destructor is automatically called to clean up the UnloadingShip. The associated memory is automatically cleaned up.
When the encompassing scope is a C++ class (that is to say a member variable):
class UnloadingBay
{
int foo;
UnloadingShip unloadingShip;
};
the lifetime is tied to the instances of the class, so when our function creates an "UnloadingBay"
void bar2()
{
UnloadingBay aBay; /*no new required, default constructor called,
which calls UnloadingShip's constructor for
it's member unloadingShip*/
// do stuff!
} /*destructor fires, which in turn trigger's member's destructors*/
the members of aBay are constructed and live as long as "aBay" lives.
This is all figured out at compile time. There is no run-time reference counting preventing destruction. No considerations are made for anything else that might refer to or point to that variable. The compiler analyzes the functions we wrote to determine the scope, and therefore lifetime, of the variables. The compiler sees where a variable's scope ends and anything needed to clean up that variable will get inserted at compile time.
"new", "NULL", (don't forget "delete") in C++ come into play with pointers. Pointers are a type of variable that holds a memory address of some object. Programmers use the value "NULL" to indicate that a pointer doesn't hold an address (ie it doesn't point to anything). If you aren't using pointers, you don't need to think about NULL.
Until you've mastered how variables in C++ go in and out of scope, avoid pointers. It's another topic entirely.
Good luck!
I'm assuming unloadingShip is an object and not a pointer so the value could never be NULL.
ie.
SomeClass unloadingShip
versus
SomeClass *unloadingShip
Well, you don't have to write so much code to check if a pointer is NULL or not. The method could be a lot simpler:
bool UnloadingBay::isEmpty() const {
return unloadingShip == NULL;
}
Plus, it should be marked as "const" because it does not modify the state of the object and can be called on constant instances as well.
In your case, "unloadingShip" is an object of class "UnloadingShip" which is not dynamically allocated (except when the whole class "UnloadingBay" is allocated dynamically). Thus, checking if it equals to NULL doesn't make sense because it is not a pointer.
For checking, if an object exists, you can consider going this way:
create a pointer to your object:
someClass *myObj = NULL // Make it null
and now where you pass this pointer, you can check:
if(!myObj) // if its set null, it wont pass this condition
myObj = new someClass();
and then in case you want to delete, you can do this:
if(myobj)
{
delete myObj;
myObj = NULL;
}
so in this way, you can have a good control on checking whether your object exists, before deleting it or before creating a new one.
Hope this helps!