Sign in to follow this  
Followers 0
Ryan_001

This error has me perplexed.

32 posts in this topic

I've come across an error that has me rather stumped.  I was testing some exception handling code and found that my program was crashing with an "Access violation reading location 0x0000000000000000." error in the <ostream> header.  Figuring it was probably a problem where I accidentally double delete'd something or forgot to release a handle somewhere I started commenting out code to try and narrow down what is causing it.  This is where things got weird.  I've been able to reproduce it with a very minimal set of code (still larger than I'd like to post here though...).  The thing is if I comment out a few functions that are never run, it will compile and run fine, no errors.  If I reintroduce the code (ie. uncomment it), these same functions that are never called and never run, it will produce the error.

 

I'm currently using VS2012 express edition.  I've tried it with both the default toolset and the November CTP toolset (with identical results).  I've tried it with both 32 and 64-bit and under both debug and release and all give the same results.  I've played with every compiler and linker setting I can think of to no avail.

 

Anyone have any idea of what I should try next?

0

Share this post


Link to post
Share on other sites

I'd have to suggest posting the code. I have no idea what to make of a null pointer access just from hearing its name.

0

Share this post


Link to post
Share on other sites

I'd have to suggest posting the code. I have no idea what to make of a null pointer access just from hearing its name.

Obviously the error is in asdf.cpp, line 42.3. Duh.

 

 

 

Anyone have any idea of what I should try next?

Aside from posting the code, try stepping through the code with a debugger if you can reliably reproduce it. It's possible you're invoking undefined behavior somewhere (earlier) and the problem is only manifesting it later in the execution. Or the error occurs immediately when the undefined behavior is invoked.

2

Share this post


Link to post
Share on other sites

Also, see if there's some sort of memory debugger that you can use. One of the first programs I turn to for things like this is Valgrind, which would give you a heads-up once various memory errors occur.

0

Share this post


Link to post
Share on other sites

Also, see if there's some sort of memory debugger that you can use. One of the first programs I turn to for things like this is Valgrind, which would give you a heads-up once various memory errors occur.

 

"VS2012 express edition"

 

Valgrind does not run on Windows.

1

Share this post


Link to post
Share on other sites

What about these functions that you comment out? Perhaps they force linking with a library that then causes some conflicts. Have seen something similar.

0

Share this post


Link to post
Share on other sites

The problem with posting the code is that when I try to bring code from other files into the main file (so I can post it all in one spot), identical copy-pasted code will cause it to go from not working, to working.  For example, here's the main part I was able to trim it down to (this does not work):

 

struct TestException : public Exception {};		// class Exception : virtual public boost::exception, virtual public std::exception

std::string GetLineNumber (const boost::exception& e) {
	std::stringstream ss;
	//ss << 15;
	return ss.str();
	}

// ----- WinMain -----
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

	bool show_exception = false;
	std::string error_msg = "No error has occured.";

	try {
		throw_detailed(TestException());
		}
	catch (const Exception& e) {
		show_exception = true;
		//error_msg = e.GetWindowsErrorMessage();
		error_msg = e.GetLineNumber();
		//error_msg = GetLineNumber(e);
		}
	
	return 0;
	}

 

Now if I uncomment the line "ss << 15;" it will compile and run fine.  Notice how the function is never called.  I was trying to include throw_detailed which consists of:

// ----- special includes -----
#include <boost\exception\detail\attribute_noreturn.hpp>


// ----- ExceptionCore -----
namespace ExceptionCore {

	typedef boost::error_info<struct tagTypeInfo,std::string> TypeMsgInfo;

	template <typename T> BOOST_ATTRIBUTE_NORETURN void ThrowException (T& e, const char* func, const char* file, int line) {
		e << TypeMsgInfo(typeid(T).name());
		e << ::boost::throw_function(func);
		e << ::boost::throw_file(file);
		e << ::boost::throw_line(line);
		throw e;
		}
	}


// ----- throw macro ----
//#define throw_detailed(x) BOOST_THROW_EXCEPTION(x)
#define throw_detailed(x) ::ExceptionCore::ThrowException(x,BOOST_CURRENT_FUNCTION,__FILE__,__LINE__)

 

into main.  But as soon as I copy and paste it in main, it works.  Basically anytime I change any of the code, related or not, it seems to change between working/not working, and I can find no pattern.  I've traced every intermediate value and with the VS2012 debugger they all are correct values at each step along the way.

Edited by Ryan_001
0

Share this post


Link to post
Share on other sites


Also, see if there's some sort of memory debugger that you can use. One of the first programs I turn to for things like this is Valgrind, which would give you a heads-up once various memory errors occur.

 
"VS2012 express edition"
 
Valgrind does not run on Windows.
I know. I never said it did. Actually, more accurately, it does: http://sourceforge.net/projects/valgrind4win/, but it doesn't work with VS.
 
 

Now if I uncomment the line "ss << 15;" it will compile and run fine. Notice how the function is never called.

One thing I can think of is that with the line uncommented, that templated member function becomes instantiated. Does it make a difference if you copy the body of this function to some other point in the code? Edited by Ectara
1

Share this post


Link to post
Share on other sites

If I copy this function below main it makes no difference.  Remove the function completely and it still causes an error.  Are you suggesting that the line "ss << 15" forces instantiation of operator<< where-as without it the member function is not?  After playing around with commenting and uncommenting the code I had a feeling the error was something to do with operator<<, but I wasn't really sure what about it.  That seems like an interesting line of attack.  Now isn't the compiler supposed to instantiate the functions automatically when it encounters them?  So would this be a compiler issue?

0

Share this post


Link to post
Share on other sites

If I copy this function below main it makes no difference.

I mean take the stringstream declaration, and use, and put it in a different function entirely, just for now.

Are you suggesting that the line "ss << 15" forces instantiation of operator<< where-as without it the member function is not?

Now isn't the compiler supposed to instantiate the functions automatically when it encounters them? So would this be a compiler issue?

When it encounters them, yes, but with it commented out, it is never used; the compiler never processes what's in comments. I'm not sure if it is implementation defined, but my compiler does not instantiate a member function if it is never called, in order to cut down on executable size. This leads to frustrating bugs that I overlook, because I never used the function, thus the compiler never instantiates it and points out an obvious bug.

So, call it a long shot, but perhaps something relies on this operator <<() function being instantiated, and when it isn't instantiated in any of the objects linked together, the program crashes. This reminds me of a compiler bug discovered not too long ago, where virtual functions were being declared as inline, and thus the compiler never instantiated the function as a normal function, leading to a crash when the program attempted to access the function through the vtable.

Defining a virtual function as an inline function is legal, and has uses, but the compiler is supposed to make a normal function instantiation as well, so that it can be called via function pointer. The bug was that the normal out-of-line instantiation wasn't made, thus the function pointer pointed to garbage. Edited by Ectara
0

Share this post


Link to post
Share on other sites

My brother, when I read your comments I get confused. So you still get the error if GetLineNumber is removed from the code. But you don't get the error if GetLineNumber is in the code, but the line ss<<15 is commented out? 

 

"Notice how the function is never called" -- but in that sample, the function was being called. I think...confused.

0

Share this post


Link to post
Share on other sites

My brother, when I read your comments I get confused. So you still get the error if GetLineNumber is removed from the code. But you don't get the error if GetLineNumber is in the code, but the line ss<<15 is commented out? 
 
"Notice how the function is never called" -- but in that sample, the function was being called. I think...confused.[/size]

There are two functions with the same name; one is a member function, one is a free function.
0

Share this post


Link to post
Share on other sites
Ah, I forgot to ask. Can you post the callstack/stack trace of where the crash occurred? It might be more obvious if you posted the ordered list of the functions that were called leading up to the crash.
0

Share this post


Link to post
Share on other sites

I think the problem you're having has to do with this thread. You're passing a temporary to that function call, but you are binding it to a non-const reference and modifying it. Technically, that's illegal C++. Visual Studio has a non-standard extension to allow you to do this, but I still don't know if it's well-defined behavior or not.

 

Try going into Project Properties -> C/C++ -> Language, and then setting "Disable Language Extensions" to true/on. You also might want to turn your warning level up to level 4 (level 3 is the default). This will help you catch mistakes like this.

 

In short, when you call throw_detailed(), don't give it a temporary object.

0

Share this post


Link to post
Share on other sites

If I copy this function below main it makes no difference.

I mean take the stringstream declaration, and use, and put it in a different function entirely, just for now.

>Are you suggesting that the line "ss << 15" forces instantiation of operator<< where-as without it the member function is not?

Now isn't the compiler supposed to instantiate the functions automatically when it encounters them? So would this be a compiler issue?

When it encounters them, yes, but with it commented out, it is never used; the compiler never processes what's in comments. I'm not sure if it is implementation defined, but my compiler does not instantiate a member function if it is never called, in order to cut down on executable size. This leads to frustrating bugs that I overlook, because I never used the function, thus the compiler never instantiates it and points out an obvious bug.

So, call it a long shot, but perhaps something relies on this operator <<() function being instantiated, and when it isn't instantiated in any of the objects linked together, the program crashes. This reminds me of a compiler bug discovered not too long ago, where virtual functions were being declared as inline, and thus the compiler never instantiated the function as a normal function, leading to a crash when the program attempted to access the function through the vtable.

Defining a virtual function as an inline function is legal, and has uses, but the compiler is supposed to make a normal function instantiation as well, so that it can be called via function pointer. The bug was that the normal out-of-line instantiation wasn't made, thus the function pointer pointed to garbage.

 

 

I understand that if commented out operator<<() would never be instantiated IF that was the only place it was used.  In this case though it was being used in another function that was being called (in this case e.GetLineNumber()) but that is in another file which is part of a small library which is linked in.  My guess is that despite being used in the library, something with the linking step is causing it to discard that instantiation, which is why the line "ss << 15" causes it to run as it forces the instantiation that should have been there in the first place.  This would also explain why copy-pasting identical code from the library into main caused it to fix itself/run.

 

So I guess the next question is, why is the linker doing this and how can I prevent it?  Did I personally do something wrong (is there a linker setting I'm not aware of?) or is this a bug with VS2012?  If my hypothesis is indeed correct, I don't see how I could have been the 1st one to come across this error.

 

btw here is the call stack:

> Zombies.exe!std::basic_ostream<char,std::char_traits<char> >::operator<<(int _Val=34) Line 300 C++

  Zombies.exe!Exception::GetLineNumber() Line 185 C++
  Zombies.exe!WinMain(HINSTANCE__ * hInstance=0x00f50000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x002a375b, int nCmdShow=10) Line 39 C++
  Zombies.exe!__tmainCRTStartup() Line 238 C
  Zombies.exe!WinMainCRTStartup() Line 164 C
  kernel32.dll!759a33aa() Unknown
  [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
  ntdll.dll!776f9ef2() Unknown
  ntdll.dll!776f9ec5() Unknown
0

Share this post


Link to post
Share on other sites

I think the problem you're having has to do with this thread. You're passing a temporary to that function call, but you are binding it to a non-const reference and modifying it. Technically, that's illegal C++. Visual Studio has a non-standard extension to allow you to do this, but I still don't know if it's well-defined behavior or not.

 

Try going into Project Properties -> C/C++ -> Language, and then setting "Disable Language Extensions" to true/on. You also might want to turn your warning level up to level 4 (level 3 is the default). This will help you catch mistakes like this.

 

In short, when you call throw_detailed(), don't give it a temporary object.

 

I didn't know you couldn't throw a temporary object, I assumed it would make a copy.  Even if that's not the cause of the error that is good to know.

0

Share this post


Link to post
Share on other sites

I didn't know you couldn't throw a temporary object, I assumed it would make a copy.  Even if that's not the cause of the error that is good to know.

The problem isn't throwing the object. The problem is modifying the temporary object, which (by standard C++) is undefined behavior. The problem is binding a non-constant reference to a temporary object and then modifying the object (not throwing the object). In the ThrowException() function, e is a reference to a temporary, and you are modifying it, which is undefined behavior. e should be a const reference, and you should not modify it (feel free to throw it).
0

Share this post


Link to post
Share on other sites

The problem isn't throwing the object. The problem is modifying the temporary object, which (by standard C++) is undefined behavior. The problem is binding a non-constant reference to a temporary object and then modifying the object (not throwing the object). In the ThrowException() function, e is a reference to a temporary, and you are modifying it, which is undefined behavior. e should be a const reference, and you should not modify it (feel free to throw it).

Is not the reference valid for the lifetime of the temporary object?  I was certain pg.245 of N3337 implies that the temporary object the reference was bound to will exist for the duration of the function, in particular 12.2.5.  Am I reading this wrong?

0

Share this post


Link to post
Share on other sites

In this case though it was being used in another function that was being called (in this case e.GetLineNumber()) but that is in another file which is part of a small library which is linked in.

Is the problematic code also part of the library? The compiler/linker is not required to ensure that only one copy of a function exists during linking, as far as I know. Additionally, if the library is compiled with different settings (optimization, debugging, secure iterators...), there must be two distinct copies, because the compiler flags are different.
0

Share this post


Link to post
Share on other sites

In this case though it was being used in another function that was being called (in this case e.GetLineNumber()) but that is in another file which is part of a small library which is linked in.

Is the problematic code also part of the library? The compiler/linker is not required to ensure that only one copy of a function exists during linking, as far as I know. Additionally, if the library is compiled with different settings (optimization, debugging, secure iterators...), there must be two distinct copies, because the compiler flags are different.

The code that calls the operator<<() in ostream, that blows up, is in the library (and moving it into the non-lib portion of the program seems to fix it).  As far as I can tell, though I guess I will check again for the 100th time, all the compiler settings for the library are the same as for the rest.  In the past when I have screwed this up though, the linker spits a whole host of 'function not found' linker errors.  In this case it seems to be building the exe fine, then just blowing up when it is run.

0

Share this post


Link to post
Share on other sites

Is not the reference valid for the lifetime of the temporary object?  I was certain pg.245 of N3337 implies that the temporary object the reference was bound to will exist for the duration of the function, in particular 12.2.5.  Am I reading this wrong?

It's kind of a weird part of C++. The reference/object exists, and it will exist for the duration of the function, but it might not really exist... Confusing? A little. There are two types of existance. The "readonly" type of existence, and the "read+write" type of existence. The object exists (in terms of being able to read it) as far as 12.2.5 is concerned. "existence" doesn't mean you can write to an object. It just means it's there.

 

I suggest reading this. One of the big reasons for this whole thing is to avoid bugs where temporaries are accidentally modified. (think of it, being able to do 2 = 1; would be weird...)

 

I also suggest reading this. It might not seem like it makes a lot of sense, and in some ways, it doesn't, but it's just one of those things in C++.

Edited by Cornstalks
0

Share this post


Link to post
Share on other sites

I don't think that's what it means.  The idea behind temporaries is that they can be bound to an r-value reference, and that they can be modified.  It'd be kinda useless to have a r-value reference to say a string if I couldn't pilfer the data by swapping the internal pointer (which implies both reading and writing to it).  If I could only read and not write the pointer then the data would be delete'd right away, which wouldn't really make sense.  There's no where I see it stated that temporaries bound to non-const lvalues cannot be modified while temporaries bound to non-const rvalues can be.  Also in your example (2 = 1), neither would bind to a non-const lvalue.  Also the standard does clearly state the temporary will live till the end of the expression (at the very least), which would include the function call.

 

Far more baffling though is why isn't the VS2012 compiler linking in the proper template function instantiations, and if I've made a mistake in the compiler or linker settings why didn't it tell me instead of just blowing up...

0

Share this post


Link to post
Share on other sites

I don't think that's what it means.  The idea behind temporaries is that they can be bound to an r-value reference, and that they can be modified.  It'd be kinda useless to have a r-value reference to say a string if I couldn't pilfer the data by swapping the internal pointer (which implies both reading and writing to it).  If I could only read and not write the pointer then the data would be delete'd right away, which wouldn't really make sense.  There's no where I see it stated that temporaries bound to non-const lvalues cannot be modified while temporaries bound to non-const rvalues can be.  Also in your example (2 = 1), neither would bind to a non-const lvalue.  Also the standard does clearly state the temporary will live till the end of the expression (at the very least), which would include the function call.

The thing is, you're not supposed to be able to take an l-value reference to an r-value. Yes, there are some ways that an r-value reference may be modified (through calling non-const member functions, or if you're using move semantics), but they're not supposed to be modified through any other means.

 

But it's possible Visual Studio allows it. I just know that in standard C++, it's illegal.

 

Far more baffling though is why isn't the VS2012 compiler linking in the proper template function instantiations, and if I've made a mistake in the compiler or linker settings why didn't it tell me instead of just blowing up...

Are you sure that's the error? The error you're describing sounds a whole lot like you're invoking undefined behavior somewhere. Are you linking to two different versions of the standard library? If you're not, then I highly doubt that is your problem, and would expect your problem to be undefined behavior being invoked elsewhere. Seriously though, at least try passing in a variable to throw_detailed() instead of a temporary.

 

Also, I suggest you post the *full* code, because that's not it. You're not showing what Exception::GetLineNumber() is, for example.

 

Somewhere you're invoking undefined behavior. I'd be shocked if the template instantiation is the problem (unless you're linking to different versions of the standard library).

0

Share this post


Link to post
Share on other sites

The function Exception::GetLineNumber() is:

std::string Exception::GetLineNumber () const {
	const int* line = boost::get_error_info<boost::throw_line>(*this);
	if (line) {
		std::stringstream ss;
		ss << *line;
		return ss.str();
		}
	return "unknown line";
	}

 

BTW I did change throw_detailed to:

template <typename T> BOOST_ATTRIBUTE_NORETURN void ThrowException (T e, const char* func, const char* file, int line) {

 

and Exception constructor looks like:

Exception::Exception (const std::string& msg) {
	*this << ErrMsgInfo(msg);
	}

 

And that's all.

Edited by Ryan_001
0

Share this post


Link to post
Share on other sites

Far more baffling though is why isn't the VS2012 compiler linking in the proper template function instantiations, and if I've made a mistake in the compiler or linker settings why didn't it tell me instead of just blowing up...

 

I have a vague recollection of accomplishing this through haphazard includes spread out unnecessarily. Also, something to do with using different versions of Visual Studio (I've usually had several version installed on the same machine). Sorry about the brain damage here...please post the solution when you find it.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0