Is there any issue if local std::function out of its "life"? - c++

Could you please help to review the below code? is there any issue if a local std::function is out of its "life"? Thanks in advance.
class Test {
public:
void commit(std::function<void()> func)
{
// return immediately
dispatch_async(conqueue, ^{
// in order to call func when it is out of "life"
sleep(5);
func(); // is there any issue? the func should be invalid at this moment?
});
}
void test() {
std::string name = "test";
std::function<void()> func = [name, this] () {
printf("%lx %s\n", &name, name.c_str());
std::cout << "callback"<<std::endl;
};
// async
commit(func);
}
//...
};

OK, I ran some tests and have changed my view on this. The code is safe because func is captured by value (i.e. the block inherits a copy).
I proved this to myself with the following test program (you will need MacOS to run this):
// clang block_test.mm -lc++
#include <iostream>
#include <unistd.h>
#include <dispatch/dispatch.h>
struct Captured
{
Captured () {}
Captured (const Captured &c) { std::cout << "Copy constructor\n"; }
void Foo () const { std::cout << "Foo\n"; }
};
int main ()
{
Captured c;
// return immediately
dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
sleep(5);
c.Foo ();
});
sleep (10);
};
Output:
Copy constructor
Copy constructor
Foo
I'm not sure why the copy constructor is called twice though. Ask Apple.
Update: There's a good writeup on working with blocks here. That's what that funny 'hat' syntax is.

It's safe. Apple "Blocks" capture non-__block variables by value, so the block contains a copy of the std::function inside it, so the lifetime of the block's copy of the variable is the same as the block itself.
(P.S. Even if the variable was declared __block, it would still be safe. Blocks capture __block variables kind of "by reference", in that multiple blocks, as well as the original function scope, share the state of the variable. However, the underlying mechanism of __block ensures that the variable is moved to the heap if it is used by a block that outlives the function's scope. So for a __block variable, its lifetime lasts until all blocks that captured it have been destroyed.)

Related

vector of threads called from inside a class function

I am trying to do something similar to the last code in this
In the code however you see that
vec_thr.emplace_back(&Test::testme, std::move(t1), std::cref(str)); is called inside the main function.
I would like to do that from a member function of the object Test.
So I did
#include <thread>
#include <string>
#include <vector>
#include <iostream>
class Test
{
private:
public:
void testme(const std::string& _str)
{
std::cout << "Hello " + _str << std::endl;
}
void testFurther(const std::string& _str){
std::vector<std::thread> vec_thr;
// pass the constructor parameters you would have passed to std::thread
// to the emplace_back() function - they are forwarded to the thread that
// is constructed "in place" inside the vector
for(int i=0;i<2;i++){
//HERE I am trying how to write this correctly trying the following:
// vec_thr.emplace_back(&Test::testme, std::move(t1), std::cref(str));
vec_thr.emplace_back(testme, std::move(this), std::cref(_str));
// vec_thr.emplace_back(testme, std::cref(_str));
}
// Don't forget to join all your threads to make sure
// they complete before moving on/exiting
for(auto& t: vec_thr)
t.join();
}
};
int main()
{
const std::string str = "there";
Test t1/*, t2*/;
t1.testFurther(str);
}
However it is not working. I got the error message
error: invalid use of non-static member function
Is there a way to be able to do this.
I want to do the exact same thing that was done originally from the main function
It seems I have solve the problem by changing the class Test function testFurther to
void testFurther(const std::string& _str){
std::vector<std::thread> vec_thr;
// pass the constructor parameters you would have passed to std::thread
// to the emplace_back() function - they are forwarded to the thread that
// is constructed "in place" inside the vector
for(int i=0;i<2;i++){
// vec_thr.emplace_back(&Test::testme, std::move(t1), std::cref(str));
// vec_thr.emplace_back(testme, std::move(this), std::cref(_str));
// vec_thr.emplace_back(&testme, this, std::cref(_str)); // ISO forbid taking the address of an unqualified or parenthesized non-static member function
vec_thr.emplace_back(&Test::testme, this, std::cref(_str)); //THIS WORKS
// vec_thr.emplace_back(testme, std::cref(_str));
}
// Don't forget to join all your threads to make sure
// they complete before moving on/exiting
for(auto& t: vec_thr)
t.join();
}
with this it seems to be working well.
I just wonder why I have to use &Test::testme since Test is the name of the class not of an object instance

Crash when using a global object, but not when using a local object

I am trying to use libconfig to create a configuration file for my program. There are two scenarios, one which works perfectly (local scope object) and the other which fails (global scope object). I am trying to understand why one fails while the other succeeds, as it is my understanding that both are definitions which create the same object (just in different scope).
1st (does not work): I define a Config object in the global scope. Then I call readFile on the Config object. The program crashes here.
#include <libconfig.h++>
libconfig::Config cfg;
int __attribute__((constructor)) Init()
{
cfg.readFile("/home/jalius/csgo-internal/hack.cfg");
}
2nd (works): I define a local Config object and call readFile on it.
#include <libconfig.h++>
int __attribute__((constructor)) Init()
{
libconfig::Config cfg;
cfg.readFile("/home/jalius/csgo-internal/hack.cfg");
}
When you are calling int __attribute__((constructor)) Init() function at that time the cfg object is not created in your case. Because the order of calling functions decorated with attribute constructor and C++ objects with static storage duration is unspecified. Since object doesn't exists so you are getting segmentation fault error i.e. SIGSEGV signal.
Following is an extract from GCC website:
at present, the order in which constructors for C++ objects with static storage duration and functions decorated with attribute constructor are invoked is unspecified. In mixed declarations, attribute init_priority can be used to impose a specific ordering.
See constructor section on this page for more information.
There is no guarantee that your function int __attribute__((constructor)) Init() will be called before the Config object is constructed.
When you try to read from it, you might actually try to access an unconstructed object. This will cause undefined behavior.
When you create it locally, there is a guarantee that your object will be initialized fully before you use it.
Experiment:
#include <iostream>
enum {
OBJECT_CONSTRUCTOR,
FUNCTION_CONSTRUCTOR,
};
int order[10], cur = 0;
class TestClass {
public:
TestClass() { order[cur++] = OBJECT_CONSTRUCTOR; }
~TestClass() { }
};
TestClass abc;
int __attribute__((constructor)) Init() {
order[cur++] = FUNCTION_CONSTRUCTOR;
}
int main ()
{
std::cout << "Order of execution:\n";
for(int i = 0; i < cur; i++)
{
switch(order[i])
{
case OBJECT_CONSTRUCTOR:
std::cout<<"Object Constructor\n";
break;
case FUNCTION_CONSTRUCTOR:
std::cout<<"Function Constructor\n";
break;
}
}
return 0;
}
Results:
Order of execution:
Function Constructor
Object Constructor

Destructor not called for local objects when we use atexit()

Please help:
I am aware about destructors and atexit() and know following too:
atexit() register a function to be called when the program terminates (e.g. when main() calls a return or when exit() is explicitly called somewhere).
When exit() is invoked, static objects are destroyed (destructor is called), but not objects in local variable scope and of course dynamically allocated objects neither (those are only destroyed if you explicitly call delete).
below code give output as:
atexit handler
Static dtor
Can you please help me knowing why destructor of local objects wont be called when we use atexit()?.
Thanks in advance:
class Static {
public:
~Static()
{
std::cout << "Static dtor\n";
}
};
class Sample {
public:
~Sample()
{
std::cout << "Sample dtor\n";
}
};
class Local {
public:
~Local()
{
std::cout << "Local dtor\n";
}
};
Static static_variable; // dtor of this object *will* be called
void atexit_handler()
{
std::cout << "atexit handler\n";
}
int main()
{
Local local_variable;
const int result = std::atexit(atexit_handler);
Sample static_variable; // dtor of this object *will not* be called
std::exit(EXIT_SUCCESS);//succesful exit
return 0;
}
Calling destructors is not about atexitbut exit.
I don't generally regard std::exit any good C++ programming. In fact, this and the std::atexit
extern "C" int atexit( void (*func)() ); // in <cstdlib>
come from the C standard library. As looking at your example, I believe you have seen http://en.cppreference.com/w/cpp/utility/program/exit, and you have also seen
"Stack is not unwound: destructors of variables with automatic storage durations are not called."
Which is the answer to your question "why"? There are some cases, particularly unrecovered errors you might make use of exit, but generally use should stick to using exceptions, e.g.,
Static static_variable;
int mainactual()
{
Local local_variable;
Sample static_variable;
throw std::exception("EXIT_FAILURE"); // MS specific
// ... more code
}
int main()
{
try
{
mainactual()
}catch ( std::exception & e )
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Create struct object in a function and pass its pointer

I am trying to pass in a empty struct pointer into a function called "initialize" as an output parameter and then after the function finishes I could retrieve the object pointed by the struct pointer. Some unexpected behaviors occur and I don't quite understand.
Below is my code:
static void initialize(complex_struct*& infoPtr)
{
complex_struct myInfo;
infoPtr = &myInfo;
// some other codes that modify the contents of myInfo
infoPtr->input_components = 3;
}
static void myfunction()
{
complex_struct* infoPtr = nullptr;
initialize(infoPtr);
std::cout << infoPtr->input_components << std::endl;
}
The output of this is an arbitrary large integer number. But I was expecting an integer 3 is printed.
Restrictions:
I cannot modify complex_struct; it is a third_party struct that needs to be used.
Also, the reason why I need initialize() to be a separate function is that I am doing performance measurement on the memory allocation of complex_struct. So moving the first line of code in initialize() to myfunction() is not an ideal solution.
You are trying to use the pointer to local variable outside of it's scope funciton. In your example, myInfo instance inside initialize() will be deleted after you exit the function, and the address you remembered will be pointing to random garbage memory. You should never use pointers to local variables outside of their scopes.
How to fix the issue? The easiest way would be to ditch the pointer here, and instead pass your struct by non-const reference. Code would look like following:
void initialize(complex_struct& info)
{
// some other codes that modify the contents of myInfo
info.input_components = 3;
}
void myfunction()
{
complex_struct info;
initialize(info);
std::cout << info.input_components << std::endl;
}
There is one subtle flaw in the suggested code: effectively info is initialized twice. First time when it's instance is created (complex_struct info) and the second time inside initialize() function. It would not have any noticeable effect in this example (info is allocated on the stack, and I do not think it has any non-trivial constructor) but might be of bigger problem in other setting. The best way to initialize it in this case would be to return the struct from the initialzer function, and rely on copy-elision to optimize away all the copies. Illustration code:
complex_struct initialize()
{
complex_struct info;
// some other codes that modify the contents of myInfo
info.input_components = 3;
return info;
}
void myfunction()
{
complex_struct info = initialize();
std::cout << info.input_components << std::endl;
}
You are returning a pointer to an object in the stack frame. That object gets deleted when the function returns. You have a dangling pointer in myfunction.
Ways to solve the problem:
Allocate memory from heap
static void initialize(complex_struct*& infoPtr)
{
infoPtr = new complex_struct ;
infoPtr->input_components = 3;
}
Make sure to deallocate the memory in the calling function.
Use an object, instead of a pointer
static void initialize(complex_struct& info)
{
info.input_components = 3;
}
and change its usage:
static void myfunction()
{
complex_struct info;
initialize(info);
std::cout << info.input_components << std::endl;
}

C++ Syntax errors

I'm trying to make a kind of screen manager in C++ but I'm getting errors.
With my code below I receive
1>screenmanager.cpp(26): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'virtualGameScreen' to 'virtualGameScreen *&&'
1> with
1> [
1> _Ty=virtualGameScreen *
1> ]
1> Reason: cannot convert from 'virtualGameScreen' to 'virtualGameScreen *'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>
Errors occur with gameScreen.push_back(gameScreenToAdd);
I get access violation error when adding a reference operator with gameScreenToAdd.
ScreenManager.h
void AddScreen(virtualGameScreen);
void RemoveScreen(virtualGameScreen);
ScreenManager.cpp
std::vector<virtualGameScreen*> gameScreen;
void ScreenManager::Initialize(void)
{
MainMenu menu = MainMenu();
AddScreen(menu);
}
void ScreenManager::AddScreen(virtualGameScreen gameScreenToAdd)
{
gameScreenToAdd.LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
So, I've hit a bit of a wall, any suggestions on how I might fix this?
edit game runs if I change gameScreen.push_back to gameScreen.push_back(new MainMenu()); buut that's not really how I want the function to work
So, the first thing the compiler did is tell you where the problem occurs:
1>screenmanager.cpp(26)
It also told you primarily what the problem is:
Reason: cannot convert from 'virtualGameScreen' to 'virtualGameScreen *'
So - something in your code is providing a "virtualGameScreen" object instance where it was expecting a pointer (denoted by the *). And it's on line 26. The other parts of the error indicate it's the call to push_back. Lets look at line 26:
gameScreen.push_back(gameScreenToAdd);
Yep - you're calling push_back, and you're passing it gameScreenToAdd, which is of type virtualGameScreen. The push_back call is from this vector:
std::vector<virtualGameScreen*> gameScreen;
Your vector expects pointers, so the push_back expects vectors.
HOWEVER: You can't just do this:
gameScreen.push_back(&gameScreenToAdd);
because gameScreenToAdd is a temporary function variable - when you call AddScreen, the original variable is copied into a new, temporary virtualGameScreen for the lifetime of the function call. That means when the program leaves AddScreen the screen whose address you pushed will no-longer exist (the memory is still there, but it has been released and the computer will now proceed to use it for other reasons).
What you'll need to do is change AddScreen to take a pointer.
void ScreenManager::AddScreen(virtualGameScreen* gameScreenToAdd)
{
gameScreenToAdd.LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
Unfortunately, this leaves you open to yet another problem with your code.
void ScreenManager::Initialize(void)
{
MainMenu menu = MainMenu();
AddScreen(menu);
}
This function creates a temporary, local MainMenu object - with a lifetime of the duration of Initialize. Then it creates a second, temporary MainMenu and copies it to menu.
If you write
AddScreen(&menu);
it will work, but it will pass the address of a temporary instance to AddScreen.
As soon as program flow leaves the "Initialize()" function, your value goes away.
It looks like you may have some prior experience with something like Java or C# and are trying to apply previous knowledge to C++.
What you need is a member variable to store "Menu" for the life time of the instance of ScreenManager.
Option 1: Just use a class member variable.
class ScreenManager
{
MainMenu m_menu;
public:
ScreenManager()
: m_menu() // initialize menu while we are initializing.
{}
void Initialize()
{
AddScreen(&m_menu);
}
// ...
};
If you really want to use a pointer, you might do the following:
class ScreenManager
{
MainMenu* m_menu;
public:
ScreenManager()
: m_menu(nullptr) // make sure it's null as soon as the object is created
{}
void Initialize()
{
m_menu = new MainMenu();
AddScreen(m_menu);
}
// but now we have to make sure it is released when we go away
~ScreenManager()
{
if (m_menu)
{
delete m_menu;
m_menu = nullptr;
}
}
};
Option 3: use C++ containers to manage the lifetime of the pointer for you, either std::unique_ptr or std::shared_ptr
---- EDIT ----
Seeing the edit you made while I was writing this, it's a little clearer what you're trying to do. What you probably want is something more like this:
std::vector<std::unique_ptr<virtualGameScreen>> gameScreen;
Consider the following:
Live demo: http://ideone.com/7Th2Uk
#include <iostream>
#include <vector>
class Foo {
const char* m_name;
public:
Foo(const char* name) : m_name(name) { std::cout << "Foo " << m_name << '\n'; }
~Foo() { std::cout << "~Foo " << m_name << '\n'; }
};
int main() {
std::vector<Foo*> foos;
Foo foo("foo");
foos.push_back(new Foo("new"));
return 0;
}
Note that the second foo is never released.
Foo foo
Foo new
~Foo foo
std::unique_ptr is a pointer-container object which will delete the object when the object expires. This makes it suitable for use in a container like std::vector
#include <iostream>
#include <vector>
#include <memory> // for std::unique_ptr
class Foo {
const char* m_name;
public:
Foo(const char* name) : m_name(name) { std::cout << "Foo " << m_name << '\n'; }
~Foo() { std::cout << "~Foo " << m_name << '\n'; }
};
int main() {
std::vector<std::unique_ptr<Foo>> foos;
Foo foo("foo");
foos.emplace_back(new Foo("new"));
return 0;
}
Both objects get cleaned up:
Foo foo
Foo new
~Foo foo
~Foo new
Now you don't need your m_menu at all, you can simply call AddScreen with a 'new MainMenu()' and the pointer will be added to the vector such that when the vector goes out of scope, proper cleanup will happen.
Menu* menu = new MainMenu();
AddScreen(menu);
or
AddScreen(new MainMenu());
In theory what you should really do is ensure that the allocation goes straight into a unique_ptr object so that there's no window for it to get leaked, but teaching the use of std::unique_ptr is beyond the scope of this answer. http://msdn.microsoft.com/en-us/library/hh279676.aspx, http://www.drdobbs.com/cpp/c11-uniqueptr/240002708, etc.
In pre-C++11 code, you might have something like this:
std::vector<virtualGameScreen*> gameScreen;
void ScreenManager::Initialize(void)
{
AddScreen(new MainMenu);
}
void ScreenManager::AddScreen(virtualGameScreen *gameScreenToAdd)
{
gameScreenToAdd->LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
but you would have to have some way to make sure the object got deleted.
With C++11, you would probably want to have the memory managed automatically:
std::vector<std::unique_ptr<virtualGameScreen>> gameScreen;
void ScreenManager::Initialize(void)
{
AddScreen(std::unique_ptr<MainMenu>(new MainMenu));
}
void ScreenManager::AddScreen(std::unique_ptr<virtualGameScreen> gameScreenToAdd)
{
gameScreenToAdd->LoadContent();
gameScreen.emplace_back(std::move(gameScreenToAdd));
}
That's because you did not provide a pointer to the vector (gameScreen), and another issue about the code is that: the paramater will generate a temp object, if just put the address of it the app maybe crash.