maybe this is the continuation of this thread,
The program compiles without errors or warnings but when I run it, and the handler function is called, I get EXEC_BAD_ADDRESS
void MainController::show_color_trackbars(int *h, int *s, int *v){
String winName = "HSV Trackbars";
namedWindow(winName, CV_WINDOW_AUTOSIZE);
std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h;
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);
};
void trackbar_handler(int value, void *user_data){//callback for the track bar
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data);
MainController *controller;
controller = reinterpret_cast<MainController *>((*user_data_map)["Object"]);
int *var;
var = reinterpret_cast<int*> ((*user_data_map)["h"]);
//do something with controller and var
};
I am mistaking something when casting? I cannot think of another reason this code is failing.
Thanks in advance
That's because in all probablity user_data_h is a local variable and is already destroyed when trackbar_handler is called. trackbar_handler works on a pointer which is no longer valid!
Please check if it is okay to have user_data_h dynamically allocated and register that pointer with the callback dispatch.
Related
I'm trying to send data from my application to the GLFW keyCallback where I then access and modify that data. However, nothing I pass in can be accessed or changed without an app crash. What am I doing wrong?
//main.cpp
typedef struct
{
string type, name;
} DebugUsrPtr;
//hot loop
{
DebugUsrPtr myPtr;
myPtr.type = "aaa";
myPtr.name = "bbb";
void *testPtr = &myPtr;
glfwSetWindowUserPointer(myWin, testPtr);
glfwSetKeyCallback(myWin, keyCallback0);
glfwSetWindowUserPointer(myWin, myWin);
}
//input.cpp
void keyCallback0(GLFWwindow *window, int key, int scancode, int action, int mods)
{
auto *myTest = static_cast<DebugUsrPtr*>(glfwGetWindowUserPointer(window));
cout << "name test = " << myTest->name << endl; // ""
myTest->name = "zzzz"; //prints "zzzz" for one frame then appcrash
}
On this line:
glfwSetWindowUserPointer(myWin, myWin);
When you set that, the user pointer will now point to the window structure, not your struct. So when the callback is called (it is called later), it no longer points to your debug structure, but to the windows pointer.
You need to send the pointer to your structure and let it there as long as you think you will need it.
You have another error, the debug structure is destroyed before the callback is called:
{
DebugUsrPtr myPtr;
myPtr.type = "aaa";
myPtr.name = "bbb";
void *testPtr = &myPtr;
glfwSetWindowUserPointer(myWin, testPtr);
glfwSetKeyCallback(myWin, keyCallback0);
glfwSetWindowUserPointer(myWin, myWin);
} // debug structure destroyed here!
So when the callback is called later, it the debugs structure will be freed, and that will lead to undefined behaviour!
For that, I think you should declare your struct in the parent scope of your event loop. Just like this:
DebugUsrPtr myPtr;
// ...
{
glfwSetWindowUserPointer(myWin, &myPtr);
glfwPollEvents(); // the callback will be called here if user press keys!
}
If you're really doing C++, declare your struct like this instead:
struct DebugUsrPtr {
std::string type, name;
};
If you want a different type or a different pointer for each callback, hold them all in a bigger struct:
struct AllPointers {
DebugUsrPtr dbg;
MouseUsrPtr mouse;
// more...
};
I was writing an interface(using FLTK but this doesn't matter). I made a button and its callback function. In this callback function I need to use data in a variable outside the callback function(which is Myclass mc in the code). The code looks like the following (I didn't paste the unnecessary parts):
class Myclass
{
...
}
void button_callback( Fl_Widget* o, void* data)
{
Fl_Button* button=(Fl_Button*)o;
Myclass *a;
a=data;
a->MyMemberFunction();
}
int main()
{
Myclass mc;
...
Fl_Button button( 10, 150, 70, 30, "A button" );
button.callback( button_callback,&mc );
...
}
However at the place of "a=data;" I got an error saying void * cannot be assigned to Myclass *, what should I do?
Many thanks!
Assuming that the data coming in through the void* is a pointer to Myclass, you need to add a reinterpret_cast from the void*, like this:
Myclass *a = reinterpret_cast<Myclass*>(data);
This will tell the compiler that you know for sure that the data is a pointer to Myclass, letting you call MyMemberFunction() through that pointer.
you need to use any kind of type casting:
here is C variant:
Myclass *a = (Myclass*)data;
here is C++ variant:
Myclass* a = reinterpret_cast<Myclass*>(data);
I have a class:
class SendData
{
public:
SendData(int SendAMsg(int foo, unsigned char *bar, int length), int number)
{
m_nDefinePos = 0;
m_nOtherStuffDefinedAs =0;
}
void somestuffhere();
void ClearDefinition();
private:
int aLotOfVariableshere;
int m_nDefinePos;
};
This is the class itself. Then some stuff is called:
SendData* m_pData;
m_pData->ClearDefinition();
Which now calls this one:
void SendData::ClearDefinition()
{
printf("Welcome to Clear Definition Script\n");
m_nDefinePos = 0;
// Some more stuff here
}
Here the code breaks somehow. I get the "Welcome to Clear Definition Script" message in my console, but that's all.
It breaks on m_nDefinePos = 0;. (I did put in another printf command after it, never showed in the console.)
I just don't know why it breaks there and i cant find any error.
SendData* m_pData;
m_pData->ClearDefinition();
This declares a pointer, but doesn't create an object or initialise the pointer to point to anything, so calling a member function via the pointer will go wrong. Perhaps you wanted to create an object:
SendData data(arguments);
data.ClearDefinition();
or perhaps you wanted to initialise the pointer to point an object that already exists:
SendData* m_pData = whatever;
While trying to find out a problem that occurs only in a release build and not in the debug build I noticed the following behaviour (String would be invalid and would not point to anything while the int would be fine). I have given code below which gives an idea of what I was going through
typedef boost::shared_ptr<MyClass> shared_cls
typedef std::deque<shared_cls> vector_def;
typedef boost::shared_ptr<vector_def> shared_vector_def;
typedef boost::unordered_map<int,shared_vector_def> inner_map_def;
typedef boost::shared_ptr<inner_map_def> shared_inner_map_def;
static boost::unordered_map<std::string,shared_inner_map_def> bcontainer;
shared_cls& SomeMethod(const std::string& symb,const int& no)
{
shared_inner_map_def tshare = bcontainer[symb];
shared_vector_def tmp = tshare->at(no);
shared_cls t = tmp->back();
return t
}
The object MyClass looks like this
class SomeClass
{
private:
int i;
std::string s;
void set_i(int rx)
{
i = rx;
}
int get_i()
{
return i;
}
void set_s(std::string rx)
{
s = rx;
}
std::string get_s()
{
return s;
}
}
Now when I use the above method as in the following code
void main()
{
shared_cls r = SomeMethod("IBM",12);
//Here r does not have a valid string s
//However it does have a valid int i
}
Now my question is in the above main when I call the SomeMethod the r returned does not have a valid string s. It has a scrambled value I found this out by using a logger. However the value of s is totally find during the function SomeMethod. I resolved this issue by not returning the shared pointer by reference.In that case it works. Why does removing the reference make it work
Your shared_cls t goes out of scope because it is defined in the function SomeMethod itself. You need to return shared pointers by value if they are defined in the scope. In the link, it is explained why it is dangerous to return the reference of a temporary object.
In the case of std::string, string has a reference counting mechanism and when it's reference is decremented to zero, it becomes invalidated and a segmentation fault may be observed in such a case. Even if member int i is returned properly, it is still undefined behavior.
how do I cast void *something to an object in standard C++?
Specifically I want want to cast void *userdata
to std::map<String, void*>
Is this possible? I am trying:
//void *user_data is a parameter of this function (callback)
std::map <String, void*> user_data_n; //this line is ok
user_data_n = static_cast<std::map<String, void *>>(*user_data); //I get the errors here.
ERRORs:
Spurious '>>' user '>' to terminate a template argument list
Expected '>' before '(' token
'void *' is not a pointer-to-object type
or is there a better way to carry information about the caller object and some other parameters I can pass to void *user_data?
UPDATE:
Ass suggested by #aaa carp I changed >> to > > and the first two errors were solved. The last is strange, Why do I get that kind of message when casting it here and not when putting that object when setting the callback?
std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h; //h was defined as int *h
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);
where createTrackbar is defined as:
int createTrackbar( const string& trackbarname, const string& winname,
int* value, int count, TrackbarCallback onChange, void* userdata);
UPDATE2:
doing this solved my problem but following the same approach, why I still get error when trying to cast objects contained in my map object?
void trackbar_handler(int value, void *user_data){
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data); //WORKED!! ;)
MainController *controller; //the same class type I put using "this" above
controller = reinterpret_cast<MainController *>( user_data_map["Object"]); //ERROR here
int *var = reinterpret_cast<int*> (user_data_map["h"]); //ERROR also here
>> should be > >
and you do not want to dereference void pointer, instead cast void pointer to desired pointer type and then dereference
#casa has already provided you with answer to second problem
When you're casting from a void *, your result will be a pointer too. So the map declaration should be:
std::map <String, void*> *user_data_n;
Second, you should use reinterpret_cast for such (potentially dangerous) casts:
user_data_n = reinterpret_cast<std::map<String, void *> *>(user_data);
Update:
As others suggested, you could simply use a static_cast as well.
Why do I get that kind of message when casting it here and not when putting that object when setting the callback?
Any pointer can be implicitly converted to void *, but when converting it back to a pointer of some specific type, you need an explicit cast.
why I still get error when trying to cast objects contained in my map object?
As already mentioned in the comments, you need to dereference the pointer before using the map object. You might want to define a reference instead to make things easier:
std::map <String, void*> &user_data_map =
*(static_cast<std::map<String, void *> *>(user_data));
An noted, the >> in that line to close your template should be > > (with a space).
Also, if user_data is a void pointer, you cannot dereference it. You could cast the pointer to another pointer type with reinterpret_cast:
std::map <String, void*> *user_data_n_ptr; //note this is a pointer to a map.
user_data_n_ptr = reinterpret_cast<std::map<String, void *> *>(user_data);
This will cast the void pointer to a std::map .
You should be careful with this. void pointers shouldn't typically be thrown around in c++. There may be a better way to do what you want and avoid void * all together.
I suppose this is for serving a C callback? It might be better to have a specialized struct which keeps all those values using the exact types. That way you'd be down to one cast for the whole thing. Something like this:
struct callback_user_data {
my_class* that;
int number;
callback_user_data(my_class* p, int i) : that(p), number(i) {}
};
// the callback
void my_callback(void* user_data)
{
callback_user_data* cbud = static_cast<callback_user_data*>(user_data);
somehow_use(cbud->that, cbud->number);
}
//call the function, passing our user data
callback_user_data cbud(this, 42);
some_function_taking_our_callback(&my_callback, &cbud);
Note that usually I have this seen (and used) this so that not a special type is passed, but only this, which has all the necessary data anyway:
// the callback
void my_callback(void* user_data)
{
my_class* that = static_cast<my_class*>(user_data);
that->f();
std::cout << that->number << '\n';
}
//call the function, passing our user data
some_function_taking_our_callback(&my_callback, this);