This error has me perplexed.

Started by
31 comments, last by iMalc 11 years ago

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.

The Four Horsemen of Happiness have left.

Advertisement

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.

There are two functions with the same name; one is a member function, one is a free function.
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.

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.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

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

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.

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).
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

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?

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.

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.

This topic is closed to new replies.

Advertisement