maybe this question will be a bit complicated and maybe i'm missing something of stupid.
I'll try to explain without any source code, because my project is big and i don't know how/where to start.
I have:
bool result = false;
bool* pointer = &result;
these variables are stored in some classes.. (not as in the above code).
When result is created, his address is something like 0x28fddc.
and the pointer variable takes this address.
Suddendly, without any reason (maybe), his address is not 0x28fddc anymore but something like 0x3a8c6e4.
With the pointer variable, i am trying to change the result var by doing:
*result = true;
But obviously, this doesn't work (and it doesn't give me any error). It will not change result var because it's in another address.
I don't know why this happens.
Can you only tell me how could this happen? And i'll try to fix.
(This classes are everytime being updated in some functions with parameters passed by reference).
For example:
void update_class(obj_class &obj);
(These names are only an example).
I hope i've been clear and if not, i'll just delete this topic.
Sorry for bad english but i'm italian :)
EDIT:
Now i'll try to provide some code..
button.h
class button
{
public:
void check_tap(SDL_Event* e);
bool* done;
}
messagebox.h:
class messagebox
{
public:
messagebox();
bool result_ok;
button btn_ok;
}
void check_tap(std::vector<messagebox> &msgbox, SDL_Event* e) {
for(unsigned int k=0; k<msgbox.size(); k++) {
msgbox[k].btn_ok.check_tap(e);
// check_tap is a function that i create for checking if the user is tapping the button with his finger or not. When the user presses the button and leaves it the done variable should become true, but result_ok seems not to be affected because his address here is different. This problem is only in this case using messagebox. I created more other buttons outside and all works perfect.
}
}
messagebox.cpp:
messagebox::messagebox() {
// Initializing things
btn_ok.done = &result_ok;
// Here, btn_ok.done gets the address of result_ok..
}
main.cpp:
std::vector<messagebox> msgbox;
msgbox.push_back(msgbox());
No, the address of variables do not change during their lifetime.
However, storing the address of a variable is problematical if the variable ceases to exist. A simple example is
#include <iostream>
int *p;
void f()
{
int i;
p = &i;
}
int main();
{
f();
std::cout << (void *)p << '\n';
// other code here
f();
std::cout << (void *)p << '\n';
}
In the above case, the two values of p may be the same, or they may differ. This is not because the address of variables change. It is because a variable, i is created each time f() is called, and ceases to exist when f() returns. The variable i in the first call of f() is, as far as your program is concerned, a distinct variable from i during the second call of f().
Depending on what happens with "other code here" in the above, the memory occupied by i in the first call of f() may be inaccessible (e.g. used for another variable) during the second call of f() - so, during the second call of f(), i will have a different address than during the first. There are no guarantees - you may also get lucky (or unlucky depending on how you look at it) and the addresses printed will be the same.
If you are getting behaviour that suggests, to you, that the address of a variable is changing then - somewhere in your code - there is a bug of some form. Typically, this will involve storing the address of a variable in a pointer, and using (or accessing the value of) the pointer after the variable ceases to exist. And any dereferrencing of that pointer (e.g. to access the variable pointed at) has undefined behaviour.
For example, any usage of *p like
*p = 42;
or
std::cout << *p << '\n';
in the main() I have given above will give undefined behaviour.
The act of assigning a pointer to contain the address of that variable does not change the lifetime of that variable.
Related
For a strictly internal class that is not intended to be used as part of an API provided to an external client, is there anything inherently evil with initializing a class pointer member variable to itself rather than NULL or nullptr?
Please see the below code for an example.
#include <iostream>
class Foo
{
public:
Foo() :
m_link(this)
{
}
Foo* getLink()
{
return m_link;
}
void setLink(Foo& rhs)
{
m_link = &rhs;
// Do other things too.
// Obviously, the name shouldn't be setLink() if the real code is doing multiple things,
// but this is a code sample.
}
void changeState()
{
// This is a code sample, but play along and assume there are actual states to change.
std::cout << "Changing a state." << std::endl;
}
private:
Foo* m_link;
};
void doSomething(Foo& foo)
{
Foo* link = foo.getLink();
if (link == &foo)
{
std::cout << "A is not linked to anything." << std::endl;
}
else
{
std::cout << "A is linked to something else. Need to change the state on the link." << std::endl;
link->changeState();
}
}
int main(int argc, char** argv)
{
Foo a;
doSomething(a);
std::cout << "-------------------" << std::endl;
// This is a mere code sample.
// In the real code, I'm fetching B from a container.
Foo b;
a.setLink(b);
doSomething(a);
return 0;
}
Output
A is not linked to anything.
-------------------
A is linked to something else. Need to change the state on the link.
Changing a state.
Pros
The benefit to initializing the pointer variable, Foo::link, to itself is to avoid accidental NULL dereferences. Since the pointer can never be NULL, then at worst, the program will produce erroneous output rather than segmentation fault.
Cons
However, the clear downside to this strategy is that it appears to be unconventional. Most programmers are used to checking for NULL, and thus don't expect to check for equality with the object invoking the pointer. As such, this technique would be ill-advised to use in a codebase that is targeted for external consumers, that is, developers expecting to use this codebase as a library.
Final Remarks
Any thoughts from anyone else? Has anyone else said anything substantial on this subject, especially with C++98 in consideration? Note that I compiled this code with a GCC compiler with these flags: -std=c++98 -Wall and did not notice any issues.
P.S. Please feel free to edit this post to improve any terminology I used here.
Edits
This question is asked in the spirit of other good practice questions, such as this question about deleting references.
A more extensive code example has been provided to clear up confusion. To be specific, the sample is now 63 lines which is an increase from the initial 30 lines. Thus, the variable names have been changed and therefore comments referencing Foo:p should apply to Foo:link.
It's a bad idea to start with, but a horrendous idea as a solution to null dereferences.
You don't hide null dereferences. Ever. Null dereferences are bugs, not errors. When bugs happens, all invariances in your program goes down the toilet and there can be no guarantee for any behaviour. Not allowing a bug to manifest itself immediately doesn't make the program correct in any sense, it only serves to obfuscate and make debugging significantly more difficult.
That aside, a structure pointing into itself is a gnarly can of worms. Consider your copy assignment
Foo& operator=(const Foo& rhs) {
if(this != &rhs)
return *this;
if(rhs->m_link != &rhs)
m_link = this;
else
m_link = rhs->m_link;
}
You now have to check whether you're pointing to yourself every time you copy because its value is possibly tied to its own identity.
As it turns out, there's plenty of cases where such checks are required. How is swap supposed to be implemented?
void swap(Foo& x, Foo& y) noexcept {
Foo* tx, *ty;
if(x.m_link == &x)
tx = &y;
else
tx = x.m_link;
if(y.m_link == &y)
ty = &x;
else
ty = y.m_link;
x.m_link = ty;
y.m_link = tx;
}
Suppose Foo has some sort of pointer/reference semantics, then your equality is now also non-trivial
bool operator==(const Foo& rhs) const {
return m_link == rhs.m_link || (m_link == this && rhs.m_link == &rhs);
}
Don't point into yourself. Just don't.
Foo is responsible for its own state. Especially pointers it exposes to its users.
If you expose a pointer in this fashion, as a public member, it is a very odd design decision. My gut has told me the last 30 odd years a pointer like this is not a responsible way to handle Foo's state.
Consider providing getters for this pointer instead.
Foo* getP() {
// create a safe pointer for user
// and indicate an error state. (exceptions might be an alternative)
}
Unless you share more context what Foo is, advice is hard to provide.
is there anything inherently evil with initializing a class pointer member variable to itself rather than NULL or nullptr?
No. But as you pointed out, there might be different considerations depending on the use case.
I'm not sure this would be relevant under most circumstances, but there are some instances where an object needs to hold a pointer of its own type, so its really just pertinent to those cases.
For instance, an element in a singly-linked list will have a pointer to the next element, so the last element in the list would normally have a NULL pointer to show there are no further elements. So using this example, the end element could instead point to itself instead of NULL to denote it is the last element. It really just depends on personal implementation preference.
Many times, you can end up obfuscating code needlessly when trying too hard to make it crash-proof. Depending on the situation, you might mask issues and make problems much harder to debug. For instance, going back to the singly-linked example, if the pointer-to-self initialization method is used, and a bug in the program attempts to access the next element from the end element in the list, the list will return the end element again. This would most likely cause the program to continue "traversing" the list for eternity. That might be harder to find/understand than simply letting the program crash and finding the culprit via debugging tools.
I'm currently reading about mixin classes and I think I unerstand everything more or less. The only thing I don't understand is why I don't need virtual functions anymore. (See here and here)
E.g. greatwolf writes in his answer here that virtual functions are not needed. Here is the example: (I just copied the essential parts)
struct Number
{
typedef int value_type;
int n;
void set(int v) { n = v; }
int get() const { return n; }
};
template <typename BASE, typename T = typename BASE::value_type>
struct Undoable : public BASE
{
typedef T value_type;
T before;
void set(T v) { before = BASE::get(); BASE::set(v); }
void undo() { BASE::set(before); }
};
typedef Undoable<Number> UndoableNumber;
int main()
{
UndoableNumber mynum;
mynum.set(42); mynum.set(84);
cout << mynum.get() << '\n'; // 84
mynum.undo();
cout << mynum.get() << '\n'; // 42
}
But what happens now if I do something like this:
void foo(Number *n)
{
n->set(84); //Which function is called here?
}
int main()
{
UndoableNumber mynum;
mynum.set(42);
foo(&mynum);
mynum.undo();
cout << mynum.get() << '\n'; // 42 ???
}
What value does mynum have and why? Does the polymorphism work in foo()?!?
n->set(84); //Which function is called here?
Number::set will be called here.
Does the polymorphism work in foo()?!?
No, without virtual. If you try the code, you'll get an unspecified value because before doesn't be set at all.
LIVE
I compiled your code in VS 2013, and it gives an unspecified number.
You got no constructor in your struct, which means that the variable before is not initialized.
Your code example invokes undefined behaviour, because you try to read from the int variable n while it is not in a valid status. The question is not what value will be printed. Your program is not required to print anything, or do anything that makes sense, although you are likely using a machine on which the undefined behaviour will only present itself as a seeminly random value in n or on which it will mostly appear as 0.
Your compiler likely gives you an important hint if you allow it to detect such problems, for example:
34:21: warning: 'mynum.Number::n' is used uninitialized in this function [-Wuninitialized]
However, the undefined behaviour starts even before that. Here's how it happens, step by step:
UndoableNumber mynum;
This also creates the Number sub-object with an unintialised n. That n is of type int and can thus have its individual bits set to a so-called trap representation.
mynum.set(42);
This calls the derived-class set function. Inside of set, an attempt is made to set the before member variable to the uninitialised n value with the possible trap representation:
void set(T v) { before = BASE::get(); BASE::set(v); }
But you cannot safely do that. The before = BASE::get() part is already wrong, because Base::get() copies the int with the possible trap representation. This is already undefined behaviour.
Which means that from this point on, C++ as a programming language no longer defines what will happen. Reasoning about the rest of your program is moot.
Still, let's assume for a moment that the copy would be fine. What else would happen afterwards?
Base::set is called, setting n to a valid value. before remains in its previous invalid status.
Now foo is called:
void foo(Number *n)
{
n->set(84); //Which function is called here?
}
The base-class set is called because n is of type Number* and set is non-virtual.
set happily sets the n member variable to 84. The derived-class before remains invalid.
Now the undo function is called and does the following:
BASE::set(before);
After this assignment, n is no longer 84 but is set to the invalid before value.
And finally...
cout << mynum.get() << '\n';
get returns the invalid value. You try to print it. This will yield unspecified results even on a machine which does not have trap representation for ints (you are very likely using such a machine).
Conclusion:
C++ as a language does not define what your program does. It may print something, print nothing, crash or do whatever it feels like, all because you copy an unininitialised int.
In practice, crashing or doing whatever it feels like is unlikely on a typical end-user machine, but it's still undefined what will be printed.
If you want your derived-class set to be called when invoked on a Number*, then you must make set a virtual function in Number.
#include <iostream>
int getID ( int k ) {
static int& r = k;
return r++;
}
int main()
{
int a = getID ( 10 );
int b = getID ( 10 );
std::cout << "a = " << a << ", b = " << b << std::endl;
return 0;
}
I don't understand why this code compiles.
How is it possible for a static reference to refer to a local variable k, which will disappear in the end of the function call).
On the second call we reinitialize the static reference with a new
variable. Please explain what happens here, how come static
REFERENCE can be "redefined" (i guess that i don't understand the
meaning of a reference to a static variable inside a method).
The language does not prevent you from binding references to objects of limited lifespan. That would make it very hard to use references.
(It does prevent you from binding references to temporaries. But a parameter to a function is an l-value, like a local variable, so it's allowed.)
But, if you write code where a reference binds to an object that it outlives, and you keep using the reference, you get undefined behavior, no diagnostic required, and most likely a segfault. It's essentially the same as a dangling pointer in C.
On the second call, you do not rebind the static reference variable to the new temporary. The static variable is only initialized once, the first time the function is called. That line is effectively skipped on all subsequent calls.
If you want a language that would catch mistakes like this for you, and make sure you don't get bitten by dangling references, you could look at Rust. The rust compiler has a "borrow checker" which will check your references for you, without imposing run-time overhead like the many well-known garbage-collected languages will. However Rust does not have static variables so there's no direct translation of that code ;)
In C++, I guess that the above mistake would likely be caught by a static analysis tool like Coverity, which will do some lifetime checking in your code when it scans it. But the C++ compiler won't do it for you, you would need to use a 3rd party tool.
How is it possible for a static reference to refer to a local variable k, which will disappear in the end of the function call).
It's totally possible. You just end up with a dangling reference, which leads to undefined behavior. But the static part isn't significant here.
On the second call we reinitialize the static reference with a new variable. [...]
No, we don't. A static variable is initialized only once. So the second time in getID(), we're still referring to the previous temporary k. Which we then increment, which is undefined behavior. One facet of "undefined behavior" is "code that looks like it works."
Consider a new type:
struct WrappedInt {
~WrappedInt() {
i = 0;
}
int i;
};
and rewrite your code to use it instead:
int getID ( WrappedInt k ) {
static WrappedInt& r = k;
return r.i++;
}
Here, we will see that once the temporary goes out of scope, and it explicitly zeroes out its value, when we reread it (with our dangling reference), we will get back 0:
int main()
{
int a = getID ( WrappedInt{10} ); // a == 10
int b = getID ( WrappedInt{10} ); // b == 0
std::cout << "a = " << a << ", b = " << b << std::endl;
return 0;
}
Is there any difference calling by pointer or returning pointer in following code?
I just try to modify my struct and get the resutl.Lest say I have a struct.
struct Address
{
const char* name; // "Jim Dandy"
int number; // 61
};
Address* Modifying2(Address* adr)
{
adr->name="Long John2";
return adr;
}
//or
void Modifying3(Address* adr)
{
adr->name="Long2 John2";
// return adr; no return
}
void print_addr2(const Address& r)
{
cout << r.name << '\n'
<< r.number << ' ' << r.street << '\n';
}
int main()
{
Address jd =
{
"Jim Dandy",
61
};
Address* jdPtr=&jd;
Modifying3(jdPtr);
print_addr(jdPtr);
//or
print_addr(Modifying2(jdPtr));
return 0;
}
Result is same but Which one is more safe? I mean well defined?
Both methods are doing the same thing. Returning the pointer is not essential.
But the most safest way is to pass the value by reference. (You haven't implement this way). Here how you must do it
void Modifying4(Address &adr)
{
adr.name="Long2 John2";
}
The only reason to return a pointer in the above example is if you want to allow chaining of calls:
Modifying2(Modifying2(jdPtr));
Which, for this particular implementation, does not make much sense since the function simply sets a value to a constant.
In all other cases, returning void is probably preferable, as you do not gain anything by returning the very same pointer that was passed in originally.
There is no real difference. Both work.
But be careful with pointers! If you assign a string longer than the init-value, you have to realloc the space the pointer is pointing to!!!!
mfg
Returning a pointer after modifying the value it points to is redundant.
In the real world other people, like us, or fellow coders in your company will be spending a lot of time in your code.
I forget who said it but you will also be spending 90% of your time pouring through someone else`s code.
If I saw your function that takes and returns a pointer at work I would be very confused why you did it, and it seems to show a lack of understanding of how pointers work and why you would pass a pointer to a function in the first place.
Don`t do it.
I have a method that takes in a reference to a vector that contains pointers to objects as the first parameter, and a reference to a pointer to an object of the same type as the second parameter. Within the method, I want to change the location referenced by the second argument to an object within the vector. Then have the changed pointer be used by the caller of the method, having the new location as its target. However, my current attempts at implementing this are failing.
The method in question:
void execute(std::vector<CanvasElement*>& elements,CanvasElement*& lastFocused)
Examples of ways I've unsuccessfully tried setting the value pointed to by lastFocused:
lastFocused = elements[0];
*lastFocused = *elements[0];
An elaboration in reply to a comment below:
The failure is that the changes inside the function are not reflected once outside the scope of that function.
I can confirm by printing the addresses stored in each pointer during the application's runtime, that the value is indeed being set within execute, but outside of execute it wasn't changed.
The assignment lastFocused = elements[0]; should work, here is a demonstration:
#include <iostream>
#include <string>
#include <vector>
typedef std::string CanvasElement;
void execute(std::vector<CanvasElement*>& elements, CanvasElement*& lastFocused)
{
lastFocused = elements[0];
}
int main()
{
std::string a = "hello";
std::string b = "world";
std::vector<std::string*> vec;
vec.push_back(&a);
vec.push_back(&b);
std::string* p = 0;
execute(vec, p);
if (p == &a)
{
std::cout << "It worked :-)\n";
}
else
{
std::cout << "It did not work :-(\n";
}
}
By the way, there are people who would argue that the following signature would be better:
CanvasElement* lastFocusedCanvasElement(std::vector<CanvasElement*>& elements)
That is, you should return a pointer value instead of changing a pointer variable.
I was able to solve this problem by storing a reference to the pointer in a vector and updating that stored reference. I do not know why setting it directly did not work, but this hack got the job done.