AccessViolationException in Release mode (C++) - memory

I'm getting the following exception when I run my application in Release mode from Visual C++.
Unhandled Exception:
System.AccessViolationException:
Attempted to read or write protected
memory. This is often an indication
that other memory is corrupt. at
_cexit() at .LanguageSupport._UninitializeDefaultDomain(Void
* cookie) at .LanguageSupport.UninitializeDefaultDomain()
at
.LanguageSupport.DomainUnload(Object
source, Eve ntArgs arguments) at
.ModuleUninitializer.SingletonDomainUnload(Objec
t source, EventArgs arguments)
This doesn't happen in Debug mode. Initially, I saw this exception on my home computer, but not work computer. When I continued to develop on my work computer, I ended up bumping into it.
Also, I found that when I added three const std::string variables the exception was thrown. If I removed then then all went well.
Another piece of information: I've found that turning off all the compiler optimizations in Release mode makes the exception go away
Something fishy is going on. Any ideas on how to track this down?
Thanks for the help,
Joe

Joe, you have a memory leak.
You're probably trying to use some memory that has been deleted.
See this article for common causes of memory leaks, and how to identify them, otherwise, search for "C++ memory profiler" + your compiler/platform, it'll give links to Memory profilers suitable for your compiler and platform, these will help track down the memory leak by watching how your program uses memory as it runs.
Hope this helps.
EDIT
How to track it down? This is off the top of my head, there may be better advice else where . . .
Find where the code crashes, it'll be when accessing the contents of some pointer (or deleting a pointer).
The problem is that that pointer has either a) never been assigned b) is already deleted.
Go through all references to pointers of that type, are they used in copy ctors/assignment operators?
If so, are it's contents being copied or just the pointer?
If just the pointer then is the containing class trying to delete the pointer? If so the first class to die will succeed, the second will throw an access violation.
If you don't explicitly code copy ctors and operator=, then you should hide them (declare private prototypes but don't implement them), this stops the compiler from generating default implementations for you.
When you hide them you'll get compiler errors everywhere they're being used, it might be that you can clean these up, or that you need to implement the copy ctor and operator= for each class.
I'm on vacation from tomorrow or two weeks, email me direct today (follow the link on my SO user page) if you've any questions on this.

Do you have any code that is #defined out for debuging in your code?
i.e.
#ifndef _DEBUG
//release only code such as liscensing code
#endif
That's one thing that could be causing the problem, and I've run into it before as well.
Another possibility is a VS issue (or whatever IDE you're using).
Try running the release .exe directly instead of through the develoment environment and see if you still have the same issue.

It's a while since I've done C++ "in anger" so to speak, so some (or indeed all) of what I say below may well be out of date.
Are you using managed C++? If not then it sounds like an uninitialised pointer. It used to be the case that all pointers were nulled in debug & I recall something about turning this behaviour off, but I can't remember the full details right now.
Are the strings overrunning their variables? Unlikely with std::string, but worth eliminating.

Couple of possibilities:
I would guess that you are reading/writing past local array end. In debug builds this may work, as memory is not tightly allocated. In release builds this is more likely to cause problems, depends on what is allocated right next to the array.
Another possibility is that you have an uninitialized pointer somewhere. VC default initializes local variables in debug mode, but not in release mode. Thus code like:
int* p;
if (p != NULL) { /* do something */ }
Typically fails on release mode.

The error message is strongly suggesting you have a memory issue, probably overwriting memory. These are hard to find, but you can find some possible solutions googling "visual c++ memory corruption tool".
The thing about memory corruption is that it's unpredictable. It doesn't necessarily have any consequences, and if it does they may not result in a crash. Crashing like that is good, because it informs you you've got a problem.
Fiddling with debug vs. release, adding or removing parts of code, changing optimization options and the like is unlikely to solve the problem. Even if it does, it's likely to crop up if any changes are made.
So, you've got a memory corruption problem. Those are almost always difficult to find, but there are tools. You need to fix that problem.
You might also look at your shop practices. Do you use less safe constructs (new arrays rather than vector<>, say)? Do you have coding standards to try to reduce risk? Do you have code reviews? Memory corruption can be insidious and damaging, and you want to avoid it as much as possible.

What your getting is a system exception from the OS. These are not handled because they are not C++ exception. However you can convert then into a C++ exception and catch them like a normal exception.
There is a great article here http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/ (page 3) that shows how to create a Windows Exception class that will catch the exception using the _set_se_translator method and throw a C++ exception. The great thing is you can get a stack from the EXCEPTION_RECORD structure, although your'll have to add that functionality to process the structure, but it will help narrow your search for that access violation.

I think the issue here is uninitialized local variable.
In Debug mode generally the variables get initialized and you don't get any exceptions.
But errors may occur in release mode because of this.
Try to look for uninitialized variable whose access may cause exception.
Suppose you have boolean local variable.
bool bRet;
In debug build bRet will get initailized to 0 and your code just works fine .
But in release it won't be 0 , it would be some random value and your code might be doing something based on bRet .It may later cause an exception because bRet value is wrong.

Related

Extra "$qqrv" appearing in symbols

Delphi XE3. I'm using the JCL Error dialog and FastMM with FullDebug turned on in my application and getting "garbage" appended to the symbols in the stack traces (both JCL and FastMM):
[74EA3D67] RaiseException
[0041815D] FastMM4.TFreedObject.VirtualMethodError$qqrv
[0054FEC5] Vcl.Controls.TWinControl.CMInvalidate$qqrr24Winapi.Messages.TMessage
when what I'd like is:
[74EA3D67] RaiseException
[0041815D] FastMM4.TFreedObject.VirtualMethodError
[0054FEC5] Vcl.Controls.TWinControl.CMInvalidate
[00548735] Vcl.Controls.TControl.WndProc
But only when the app is compiled for Release. When I compile for Debug the stack trace is "clean". Since I'm seeing the same sort of "garbage" in FastMM and JCL reports I don't think it's either library giving trouble.
And I'm saying "garbage" with quotes because the $qqv seems to be constant and the rest of the string varies from run to run.
I have checked (and rechecked) the map file and symbols settings and the JCL symbols and I can't see anything different in the settings.
EDIT:
Not surprisingly the underlying cause is the same, as FastMM is (I think) using JCLDebug to generate the stack traces ... so fix one, fix all.
This is a bug in the .map file parser of the JCL.
see
http://sourceforge.net/p/fastmm/discussion/443400/thread/82b024dc/
for the detailed thread and suggested fix.
Probably your Release configuration doesn't include stack frames compiler option (by default, it doesn't). Without this information compiled into the executable, what the stack trace shows are the names of the runtime package exports. The solution is to compile in Debug mode, or turn on stack frames in the compiler options of your Release configuration.
After looking into it all I conclude that this is no problem, just my misunderstanding and maybe a bit of stale code:
The $qqrv and the other text is all valid and potentially useful information so rather than find a way to remove it it would be better to learn how to use it. The links in the questions above give good basis for this work.

Do we have to set all properties to nil in -init or is this happening automatically?

I always believed that the runtime automatically initializes all properties with nil when an object is created.
But the release build for the App Store is different than the debug build during development. I have heard Xcode creates more stable builds for debugging with various security check mechanisms around variables and properties that prevent crashes but bloat up the code.
When you build for distribution, so is the myth, compiler optimizations strip out this "unnecessary" debug code to make the code faster.
I have already experienced mysterious bugs that suddenly happened in release builds.
But now a developer also told me this: In the release build, the runtime does NOT set the properties to nil. They are uninitialized. Their value is garbage memory, unless you do it manually. So !foobar is not safe to check unless you initialize the properties with nil.
So far all my apps always assume properties are nil unless I set an object.
Is this correct or does the runtime still initialize our properties to nil when we create an object?
The developer in question is wrong and you should hold any other "advice" they've given you as highly suspect.
All instance variables, including those synthesized by #property, will always be zeroed out on allocation by the Objective-C runtime. This has been the defined, documented, behavior of the Objective-C runtime since the language's inception.
Static variables will always be initialized to zero/nil/NULL, too. Local variables will be uninitialized under manual-retain-release and initialized to zero/nil/NULL when using ARC.
There are two key differences between DEBUG and RELEASE builds:
the linker will strip away any debugging symbols. This makes the code harder to debug, but makes the executable considerably smaller.
the optimizer will optimize for code size and speed.
It is that second one that causes the "mysterious" changes in behavior between DEBUG and RELEASE. The optimizer will re-use stack space and re-order operations in the code (that can be re-ordered; method calls cannot, for example) as necessary to make the code faster and smaller. This tends to uncover bugs that exist in DEBUG builds, but aren't tripped because the compiler isn't moving stuff about on the stack.
You'll be fine assuming nil.
The compiler doesn't really do anything different in release builds - I think it strips out debug stuff (NSLogs, breakpoint handlers, exception pausing, etc.) only.

How to change XCode ios SDK compiler settings to allow void return statements for non void methods?

I have been asked to update a old ios application built in Xcode 3.1 with some ios 6 features.
When I tried building the source using my xcode 4.5, it refuses to compile because there are numerous places in the project where simple return statements are used in methods which actually is supposed to return a boolean or similar value.
Xcode 3.1 allows it and 4.5 does not. Somewhere in the middle, apple decided to add this restriction.
My problem is that the code is over 20,000 lines of code and the developers have used the simple return statements where ever they needed the method to stop execution. Since the compiler stops compilation when it encounter's the first of these errors, I have to fix it one at a time and then try compiling it again only to find another error. I tried like 2 hours fixing 100s of such return statements.
Is there a compiler flag or Xcode build setting that would change these errors as warnings and allow me to run this app on Xcode 4.5?
This is the exact error that Xcode throws :
/Users.../Classes/WaterMaps.m:5471:5: Non-void method 'initWithParams:mass:radius:totalAssetInfo:' should return a value
Please help..
This has nothing to do with Xcode, but with the compiler. And not Apple added this restriction, the compilers are not from Apple, they are OpenSource projects (GCC and LLVM/clang).
May I ask why it took you 2 hours to fix 100 such return statements? Fixing 100 such return statements shouldn't take much longer than 5 minutes.
Write return 0; somewhere, select it, copy it to clipboard (CMD+C), delete it again.
Write return; somewhere, select it, hit CMD+E to copy it to search buffer, delete it again.
Go to your source code.
Hit CMD+G which means "find next".
If the found expression is not marked as error, go to (4).
Hit CMD+V (paste), which overwrites return; with return 0;.
Got to (4).
So basically you keep hitting CMD+G to jump through the file and CMD+V whenever you see an error. To quickly jump to the next file, open the error view in Xcode:
Select the first error of the first file and whenever your CMD+G procedure reaches the end of the file, hit CMD+' which jumps to the first issue of the next file on the list. As a developer, you should really learn to use your keyboard more effectively. Keeping your hands on the keyboards makes you hundreds of times more productive than going forth and back between keyboard and mouse/touchpad/trackball/etc.
And how is the amount of code lines ("over 20'000 lines of code") even relevant? It's the amount of return statements that is relevant.
Your code is currently seriously broken and instead of wasting time on thinking how to make this broken code compile, I strongly recommended that you should rather go and fix it. Since once fixed, it will work forever and not break again the next time the compilers are updated and your last hack doesn't work any longer.
I mean how shall a compiler know what you want to return for a method that returns a boolean or an int value if you only type return? The suggested `return 0;' works for all methods that return a numeric value (including floating point) and booleans (0 = false/NO) and makes the compiler happy again. It is the same value that was returned by ancient C compilers in that case.
Note that even in Xcode 3.1 those return statements should have produced warnings all over the place. As a serious developer, always treat all warnings as errors. You project should not have any warnings. Warnings tell you that there is something wrong or at least there might be something wrong and that means you should go out and fix it. Almost all warnings can be silenced by modifying your code. So instead of ignoring warnings or disabling them in the compiler, fix them. Many companies have a zero warning policy today and if your code produces only a single warning, it is rejected. If the author of this code had treated all warnings as errors, you wouldn't have to fix those now.

Access Violation unless I clean before recompile

I am receiving an access violation after I recompile a certain unit (MyClass) unless I do a clean. The error is clearly a call to a null object (Write of address 00000000), but when I try to step to it, the compiler won't allow me to step into the code where I think the error is occurring. (Inside a method on the same object. When i trace into the method, there error after hitting trace into but before going to the line of code.) This happens in a used unit of MyClass, rather than MyClass itself.
The weird thing is that if I do a clean (or build) and then recompile, the program runs fine. Any reason this would happen?
Update
The application uses several threads created via the AsyncCalls library. I use several TEvent and TMultiReadExclusiveWriteSynchronizer objects to keep processes ordered and resources protected. Does any special care need to be taken when creating or freeing such objects?
Please check the Output-Path in Project-Settings.
Set an Output-Path (e.g. ".\$(Config)\_dcu") for compiled Units and then check again.

ARC conversion tool issues: flagged retain/release, and random parse errors

I'm revisiting an an older project and converting to ARC, my first time through Xcode's conversion tool (Edit -> Refactor -> Convert to Objective-C ARC...), and I'm seeing a couple things that I'm not sure are real issues or red herrings somehow.
I get, as expected a big list of things that the tool finds that prevent it from completing, but:
Many (all?) instances of retain/release/autorelease appear to be flagged as errors e.g. "release is unavailable: not available in automatic reference counting mode". Am I really supposed to get rid of all these myself? I thought that's what the tool did.
In many of my classes, I'm seeing a bunch of errors that look like phantom parse/build errors that have nothing to do with ARC. E.g. in a simple class that apparently has no ARC-related issues, I'll get an "undeclared identifier" on some arbitrary method implementation, and then a bunch of "Parse error: expected }" at the end of the file, etc. These are not real-- the project builds fine, and I don't see any proximate cause or resolution for the errors.
There are "real" issues in the list as well (expected bridging issues that need to be explicitly clarified in code) but there are so many random errors of the above variety that it's hard to even find the signal in the noise. This seems wrong to me.
Am I misunderstanding what this tool is really doing? Apple's docs say this:
Xcode provides a tool that automates the mechanical parts of the ARC
conversion (such as removing retain and release calls) and helps you
to fix issues the migrator can’t handle automatically
Thanks.
The tool does not get rid of them for you, but simply adds retain/release code as need under the hood at the time of compile.
Those problems very well may go away when you get rid of old reference counting code.
EDIT: Further explanation:
In Xcode 4.2, in addition to syntax checking as you type, the new
Apple LLVM compiler makes it possible to offload the burden of manual
memory management to the compiler, introspecting your code to decide
when to release objects. Apple’s documentation describes ARC as
follows:
“Automatic Reference Counting (ARC) is a compiler-level feature that
simplifies the process of managing object lifetimes (memory
management) in Cocoa applications.”
In other words, ARC does not "strip" reference counting from your code, but rather does it on it's own under the hood. You no longer have to type release or retain or dealloc again. One thing the ARC needs to work is for it to do the reference counting entirely on it's own (with no user reference counting to "get in the way").
Took a long time to resolve, but both of these issues seemed to stem from some custom macros I was using. I had a macro for release-and-set-to-nil that I was using frequently, like this:
#define RELEASENIL(x) [(x) release]; \
(x) = nil;
I'm still not sure why, but for some reason, the ARC conversion tool didn't take this in stride, and choked on it, throwing the release warnings and the parse errors. (Some interaction with the preprocessor?) When I changed the macro to remove the release line, the conversion proceeded much more in line with my expectations.
And yes, it does of course remove the messages for you. (I'm answering my own question on the off chance that someone else ever has this issue.)

Resources