Whenever I output a particular pointer address to std::cout, I get a crash:
bool MyClass::foo() const
{
std::cout << "this prints fine" << std::endl << std::flush;
std::cout << d << std::endl << std::flush; // crash!
return true;
}
Where d is a pointer member of the class, i.e.:
class MyClass {
// ...
private:
MyClassPrivate* d;
};
What could cause the application to crash? Even if it is a NULL pointer, or an initialized pointer, it should still print out the (perhaps invalid) address, right?
The application is compiled in debug mode, if that makes a difference. The function foo is not marked as inline.
Background: I am trying to track down a bug in an external application process. The bug is only caused when another application sends rapid-fire command to the process. I'm using std::cout to trace the execution of the external process.
If this is not a valid pointer, any access to a member field might cause an access violation. Non-virtual methods called on invalid pointers work just fine until they try to access a field, because the call itself doesn't need to dereference this.
For instance, this situation would crash roughly as you describe:
MyClass* instance = nullptr; // or NULL if you're not using C++11
instance->foo(); // will crash when `foo` tries to access `this->d`
There could be an overload of operator<<(ostream &, MyClassPrivate*), that dereferences the pointer. For example there certainly is if MyClassPrivate is really char.
Try std::cout << (void*)d;, see whether or not it makes a difference. If not, zneak's answer seems plausible.
Related
I ran into a nasty bug in some of my code. Here's the simplified version:
#include <iostream>
class A
{
public:
std::string s;
void run(const std::string& x)
{
// do some "read-only" stuff with "x"
std::cout << "x = " << x << std::endl;
// Since I passed X as a const referece, I expected string never to change
// but actually, it does get changed by clear() function
clear();
// trying to do something else with "x",
// but now it has a different value although I declared it as
// "const". This killed the code logic.
std::cout << "x = " << x << std::endl;
// is there some way to detect possible change of X here during compile-time?
}
void clear()
{
// in my actual code, this doesn't even happen here, but 3 levels deep on some other code that gets called
s.clear();
}
};
int main()
{
A a;
a.s = "test";
a.run(a.s);
return 0;
}
Basically, the code that calls a.run() use to be used for all kinds of strings in the past and at one point, I needed the exact value that object "a.s" had, so I just put a.s in there and then some time later noticed program behaving weird. I tracked it down to this.
Now, I understand why this is happening, but it looks like one of those really hard to trace and detect bugs. You see the parameter declared as const & and suddenly it's value changes.
Is there some way to detect this during compile-time? I'm using CLang and MSVC.
Thanks.
Is there some way to detect this during compile-time?
I don't think so. There is nothing inherently wrong about modifying a member variable that is referred by a const reference, so there is no reason for the compiler to warn about it. The compiler cannot read your mind to find out what your expectations are.
There are some usages where such wrong assumption could result in definite bugs such as undefined behaviour that could be diagnosed if identified. I suspect that identifying such cases in general would be quite expensive computationally, so I wouldn't rely on it.
Redesigning the interface could make that situation impossible For example following:
struct wrapper {
std::string str;
};
void run(const wrapper& x);
x.str will not alias the member because the member is not inside a wrapper.
So lets say I have:
struct test {
bool a;
int b;
};
int main()
{
std::unique_ptr<test> ptr;
// don't init the ptr
try
{
if (!ptr->a)
{
std::cout << "ok" << std::endl;
}
}
catch (const std::exception &ex)
{
std::cout << "ex: " << ex.what() << std::endl;
}
return 1;
}
So here I setup a unique pointer, but I don't init it (to simulate this in a larger code base) but I want to catch the exception.
The problem is that my exception is not called - I just get a crash (memory access fault)
I read a few similar questions (but not quite the same) that suggested that I pass the exception by reference - but this did not work.
So is it possible to catch a unique_ptr de-reference exception?
EDIT: I should add that this is on Windows 7 box running MSVS2012 executable - incase it is relevant!
So is it possible to catch a unique_ptr de-reference exception?
There is no unique_ptr dereference exception to catch.
As the documentation says,
The behavior is undefined if get() == nullptr
You can easily write your own smart pointer with this Java-like behaviour, but it does mean paying for a test-and-branch on every dereference, which in general seems silly.
For the slightly different problem described in comments:
I have a list of unique_ptr's - I was trying to avoid individually checking each one by putting a try block around it.
the sane solution is probably to check it once and not on every subsequent dereference:
if(any_of(begin(ptrs), end(ptrs), logical_not<unique_ptr<test>>{})
{
throw MyNullPointerException();
}
Per subsequent comments, you could just add a check-and-throw wrapper to your constructing function.
In C++17 you can almost get what you want by instead returning an optional<unique_ptr<test>> (ie, it either contains a populated unique_ptr, or nothing at all: in that case, calling value to extract the unique_ptr would throw std::bad_optional_access if there isn't really one there).
If you can import ot (or don't have C++17), the GSL is probably even better with gsl::not_null<T>. For example, you could instead store these things in your container
using unique_not_null = std::unique_ptr<gsl::not_null<test>>;
I've tested the following program on gcc-4.8 (via Coliru) and on Visual Studio 2013 RC:
#include <iostream>
#include <functional>
using namespace std;
struct foo {
void bar() {
cout << "this = " << this << endl;
}
};
int main() {
try {
foo *ptr = nullptr;
function<void ()> fun = bind(&foo::bar, *ptr);
fun();
} catch (const bad_function_call &e) {
// never reached
cout << "bad_function_call thrown: " << e.what() << endl;
}
cin.get();
}
I understand I'm causing undefined behavior here by dereferencing nullptr, but I don't understand the output of my code. In my understanding this should either cause a bad_function_call (because that is what should be thrown when calling this std::function, from what I guessed) or at least print "this = 0".
It doesn't. The output is "this = " followed by some pointer which is not nullptr on both compilers I tested. Accessing it causes a segmentation fault, though.
Is there a clause in the standard specifying this? Or is it just implementation-defined "undefined behavior"?
Edit: Just as an addition: The following code outputs "this = 0" on my machine:
foo *ptr = nullptr;
ptr->bar();
What happens is that bind stores a copy of the argument. The argument is of type foo (since you are passing *ptr) and hence a copy is made. The copy, of course, gets an invalid argument as source, but that is not used and hence this seems to work. As a result, a new instance of foo is stored inside the bound object and this is the address you see.
When you say you see a segmentation fault, you refer to your real code, not the example you gave here, right? In your real code I guess the copy-ctor seems to work but creates an instance which causes the segmentation fault when you access its (probably invalid) members.
"Undefined" means undefined. Reasoning about what happens when you have undefined behavior is futile unless your compiler documents what it does.
I'm having trouble understanding why this code works. I've been in the C# world for awhile and wanted to brush up on C/C++ before diving into the new stuff in C++11 like RValue Refs and move semantics.
I'm wondering why this code that I wrote works:
class InnerMember
{
private:
int _iValue;
public:
InnerMember(): _iValue(0) {};
InnerMember(int iValue) : _iValue (iValue) {};
int GetValue(void) { return _iValue; }
int SetValue(int iValue) { _iValue = iValue; }
};
class TestClass
{
private:
InnerMember _objValue;
public:
TestClass() : _objValue(1) {};
void SetValue(int iValue)
{
_objValue.SetValue(iValue);
}
InnerMember& GetRef(void)
{
return _objValue;
}
virtual ~TestClass() { std::cout << "I've been released!" << std::endl; }
};
int main (int argc, char *argv[])
{
TestClass* pobjTest = new TestClass();
std::cout << "Before:" << std::endl;
std::cout << pobjTest->GetRef().GetValue() << std::endl;
pobjTest->SetValue(5);
InnerMember& robjInner = pobjTest->GetRef();
delete pobjTest;
std::cout << "After:" << std::endl;
std::cout << robjInner.GetValue();
return 0;
}
The output is:
Before:
1
I've been released!
After:
5
Press any key to continue...
I thought that this would cause an error, since I access the referenced object InnerMember from TestClass after TestClass has been destroyed. Is there some sort of return value optimization going on? Or is it really returning a copy instead of passing back the reference?
I used GCC to with no optimizations (-O0) and it still ran without an issue.
I also used the -S switch to generate the assembly but my AMD64 knowledge is rusty and the name mangling didn't help.
That is undefined behaviour, which means even the "correct" behaviour could happen. When you delete something in C++, it is not erased from the memory, so accessing it before something else writes over it will sometimes maybe still work.
robjInner is still a reference to some deleted object in memory.
This would lead to undefined behaviour.
After deletion, the reference robjInner has been left dangling. You get back the previous value because no one else claimed that piece of memory yet.
Copied from here
A previously-valid reference only becomes invalid in two cases:
If it refers to an object with automatic allocation which goes out of scope,
If it refers to an object inside a block of dynamic memory which has been freed.
The first is easy to detect automatically if the reference has static scoping, but is still a problem if the reference is a member of a dynamically allocated object; the second is more difficult to assure. These are the only concern with references, and are suitably addressed by a reasonable allocation policy.
You can add a print statement inside InnerMember destructor to see what is going on. You will see InnerMember is destroyed after TestClass and the 5 you get is because no one write to that part of memory yet. But that reference is not valid anymore.
i have a complex program with weird bug that some int value is down to zero unexpectedly.
so i want tracking this built-in type value, then i could debug easily.
to do that, i made following ValueWatcher template class so i could track almost changes of value except when ValueWatcher is dereferencing. (i made these dereferencing operators because the program needs int *, &)
template <typename T>
class ValueWatcher
{
public:
ValueWatcher(const T &val)
{
cout << "constructor with raw value " << val << endl;
_cur = _old = val;
}
ValueWatcher(const ValueWatcher& vw)
{
cout << "constructor with ValueWatcher " << vw._cur << endl;
_cur = vw._cur;
}
ValueWatcher& operator=(const ValueWatcher &rhs)
{
cout << "operator= with ValueWatcher " << rhs._cur << endl;
_cur = rhs._cur;
onChanged();
return *this;
}
ValueWatcher& operator=(const T &val)
{
cout << "operator= with " << val << endl;
_cur = val;
onChanged();
return *this;
}
int *operator&()
{
cout << "addressing operator" << endl;
// can't track anymore!!!!!!!!!!!!!!!!!!!!!!!!!
return &_cur;
}
operator int&()
{
cout << "operator int&" << endl;
// can't track anymore!!!!!!!!!!!!!!!!!!!!!!!!!
return _cur;
}
operator int&() const
{
cout << "const operator int&" << endl;
return _cur;
}
operator int() const
{
cout << "operator int" << endl;
return _cur;
}
private:
void onChanged()
{
// update old and do proper action
}
T _cur;
T _old;
};
the problem is, when client code wants int & or int * of ValueWatcher, - it can gives int & or int * anyway but - int * or & cannot hold ValueWatcher instance, so can't tracking anymore.
is there anyway to solve this? i think it can be solved by returning reference or pointer class instance instead of just returning & or * of built-int type. but i don't know how to do that.
in addition-
i can't run this program with debugger. the problem occurs only in REAL environment and very hard to reproduce.
If you can reproduce the behavior when running in a debugger, you should be able to set a value change or memory change breakpoint. This is probably easier than introducing a proxy implementation.
Its probably not the best solution, but what if your * or & return a pointer/reference to your value watcher? Otherwise I would forbid the use of * or &. (By not implementing it or making it private).
I don't think this is possible. Once you return an int* or int&, you've lost the ability to track anything. The only way (and the correct way, IMO) to do it that I can think of is to use a debugger and set a watch point with an appropriate condition. When the condition is met the debugger will interrupt and halt the program so you can inspect the memory, call stack, etc.
If you can spare a PAGE_SIZE bytes for your variable, then you can lock this part of memory using VirtualProtect (if you're on windows) - you can set read only access, for example. After that, anything that tries to access that variable will crash the program (so you'll be able to write memory dump and pinpoint routine that changes variable). I used this technique to pinpoint similar problem (multithreaded app, something was randomly overwriting memory blocks). If you can't debug machine immediately, try writing dumps using MiniDumpWriteDump . You will be able to debug memory dumps using WinDBG or Visual Studio.
If you're seriously desperate:
#define int ValueWatcher<int>
In a better scenario, you'd use
//typedef int intt;
typedef ValueWatcher<int> intt;
Then re-write all your code that wants an int and replace it. Replace int* with intt*. Replace int& with intt&.
You say you only see this problem when not debugging, so I'm guessing you have a bug which is obscure and can only be seen when building with optimizations. There are a couple possible explanations for this behavior:
You have a race condition somewhere
You didn't initialize a variable properly... so when building with optimizations you're values are initialized differently than when debugging.
You have a buffer overrun somewhere which is writing over one of your variables. Again, this could be something you only see when built with optimizations... When you build for debugging the compiler is going to leave extra space around variables on the stack... which acts as a cushion and can keep some bugs from revealing themselves.
Here is a relevant SO post which explains these issues in more detail:
Program only crashes as release build -- how to debug?