Caught OutOfMemoryException makes debugging difficult - c#

When I debug my program, and try to do certain things in the immediate window, it sometimes shows an error message in the immediate window saying:
The function evaluation was disabled because of an out of memory
exception.
It also shows that when viewing the properties of object by hovering over them.
After trying to find the cause of the problem, I narrowed it down to this small code sample:
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
try
{
//outofmemoryexception can be thrown by Image.FromFile("path/that/does/not/exist.png")
//if the path points to a file that is not an image
throw new OutOfMemoryException();
}
catch (OutOfMemoryException ex)
{
//caught the exception
//so no problem, right?
}
//Random object to use in immediate window
Random rand = new Random();
//Also, try hovering over this regex and take a look at its properties.
var test = new Regex("");
//put a breakpoint here (at the next closing curly brace) and try calling rand.Next() in the immediate window
}
}
}
It seems that the debugger freaks out when an OutOfMemoryException occurs, even when it's caught...
I can imagine that no one ever thought it would be possible to debug a program that has had an OutOfMemoryException. But sadly enough Image.FromFile throws that error when the file is not an image...
Questions:
Does the above code sample give problems to anyone else?
Can someone clarify this a bit? Why does this happen exactly?
And lastly, how can I prevent this?

Yes, it is expected behavior.
You need to let debugger to run (step over or put breakpoint on next line and click F5) for it to recover from such state. Even that sometimes it does not help and running till you hit some other function higher on the stack usually makes debugger to cooperate again.
Note that OOM is not the only case - i.e. long running code in Immediate window will get debugger into the same state.
More information - MSDN Function evaluation is disabled..., SO - Function evaluation disabled because a previous function evaluation timed out

Related

App.MobileService.LoginAsync fails to show dialog on select machine -> Mind Blown

Just wondering if anyone might be able to point me in the right direction here.
user = await App.MobileService.LoginAsync(provider)
this is the line of code in question. The problem is; this works fine on 2/3 test machines (All Windows 10), the dialog is displayed and the program operates as expected. on the third machine however, the dialog does not display. I have wrapped the function in a try catch block and I am catching all exceptions that I then route to a MessageDialog to display on the screen. the messages are never shown, as though the try succeeded, but the function exits on that line exactly and throws no exceptions. I am using MobileServiceAuthenticationProvider.MicrosoftAccount as my provider.
Code redacted to highlight the error, the full code returns a boolean value for success/failure. All traces past the failing line do not appear, so the function is definitely exiting at the specified line.
try
{
//This line fails on a single machine out of three
user = await App.MobileService.LoginAsync(provider)
}
catch(Exception e)
{
//when it fails, this does not trigger, and no traces after this point
//appear until outside the function
MessageDialog msg = new MessageDialog(e.ToString());
await msg.ShowAsync();
}
and just to make things really weird...message dialogs prior to this point in the code work just fine...
I suspect that the security of the machine in question is blocking the login (windows defender), but I really have no idea where to look for this, or even how to test the problem further. Any ideas as to what would prevent this single machine from displaying the Microsoft login window, or ideas on further debugging would be appreciated.
You are not awaiting the response from the Async reply. This means that you will have an ordering and concurrency issue - sometimes it will work, and sometimes it won't and it's all in the timing.
You need:
var user = await client.LoginAsync(provider);

uglify crashing after running child_process.execFile

EDIT 2
I "solved" the problem, but I don't want to post it as an answer b/c it doesn't explain what actually happened. In the code for the .NET resourceReader.exe I use
Console.OutputEncoding = System.Text.Encoding.UTF8;
to output the internationalized resources to stdout in unicode. If I reset the encoding at the end of my program with
Console.OutputEncoding = System.Text.Encoding.Default;
then I don't get any errors in Node. If I don't reset it, I get the error described in the original question. It seems that .NET is somehow messing up some of the output encoding settings on the cmd.exe and causing the subsequent node run to fail!
EDIT
I narrowed down the error to being caused by resourceReader.exe. It's a.NET program which reads some resource streams out of the .NET assembly and prints them to the stdout using Console.WriteLine. I added Console.OutputEncoding = System.Text.Encoding.UTF8 to resourceReader.exe because some of the resources are in non ASCII letters and that's whats causing the crash in grunt!
If I take that line out, the task doesn't crash, but the resources show up in non printable ASCII characters! Also, the crash only happens if I actually print non-ASCII to sdtout. If I don't print them, it doesn't error.
ORIGINAL
I added a step to my Gruntfile which uses child_process.execFile to run an read some data from an external program and uses it in the build. Now whenever I run my build, it runs fine the first time, but crashes the second time!
Here's the output from the crash (this is during the uglify task):
File build/Scripts/NDB.contacts.min.js created: 16.85 kBevents.js:85
throw er; // Unhandled 'error' event
^
Error: This socket is closed.
at WriteStream.Socket._writeGeneric (net.js:656:19)
at WriteStream.Socket._write (net.js:709:8)
at doWrite (_stream_writable.js:301:12)
at writeOrBuffer (_stream_writable.js:288:5)
at WriteStream.Writable.write (_stream_writable.js:217:11)
at WriteStream.Socket.write (net.js:634:40)
at Log._write (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:161:26)
at Log.wrapper [as _write] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
at Log._writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:166:8)
at Log.wrapper [as _writeln] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
at Log.writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:177:8)
at Log.wrapper (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
at writeln (C:\...\node_modules\grunt\lib\grunt\fail.js:30:13)
at Object.fail.fatal (C:\...\node_modules\grunt\lib\grunt\fail.js:46:3)
at process.uncaughtHandler (C:\...\node_modules\grunt\lib\grunt.js:121:10)
at process.emit (events.js:129:20)
at process._fatalException (node.js:236:26)
at Task.runTaskFn (C:\...\node_modules\grunt\lib\util\task.js:250:7)
at Task.<anonymous> (C:\...\node_modules\grunt\lib\util\task.js:293:12)
at C:\...\node_modules\grunt\lib\util\task.js:220:11
at process._tickCallback (node.js:355:11)
Here's the code for the task which uses child_process.
function readAllCultures() {
var readDeferred = q.defer();
childProc.execFile("../tools/resourceReader.exe", function (err, stdout, stderr) {
if (err) throw new Error(err);
var cultures = JSON.parse(stdout);
readDeferred.resolve(cultures);
});
return readDeferred.promise;
}
Here's some things I discovered debugging that might be helpful
If I redirect the output of grunt (using either > filename or | process) it runs fine
When I redirect output, I never see the message from uglify that it created the main output only that it created the source map.
If I close and reopen my command prompt (cmd.exe) it works fine
I added a listener to the exit and close events of the child process using rdr.on("close", function() { console.log("close"); }); and the same for exit. Both events fire as expected in the first run.
Using Process Explorer, I can see node.exe open under the command prompt and close again when my command finishes running. There are no processes visibly "left open" under the command prompt.
The fact that the stack trace is ultimately showing a socket.write error is interesting. Nothing in the code you've provided suggests you are trying to write to a socket.
If we follow the stack down, we can see that it's actually grunt that is trying to write to a socket, as it's attempting to log an uncaught exception.
So, first your grunt task throws a currently unknown error, and then grunt itself errors because it can't tell you about it.
I would first try and log the error that occurs in your child process. Currently if there is an error present, you simply throw it without finding out what it is. It's likely that this is what grunt is trying and failing to log.
Replace
if (err) throw new Error(err);
With
if (err) console.error(err);
This will hopefully avoid the socket.write problem and give you specific information about what error is happening on the child process. What do you see?
Second, I would try using child_process.exec instead of child_process.execFile. This will spawn a shell and run resourceReader.exe inside of it (instead of running it directly). This might help avoid any problems you are encountering with the command still running/failing in the background, which could be the cause of the socket.write error.

Code Execution stops with no error

In my Form1_Load event, the code execution stops for no reason the middle of nowhere, and just finishes the loading process at that instance, showing the gui, this is the code and the line where it stops:
Downloadn("https://somelinkhere.com/file.txt","Init.txt");
Application.DoEvents();
List<string> links = new List<string>();
var lines = File.ReadAllLines("Init.txt"); //Code Stops and Gui Shows up after executing this code
links.Add(lines[0].Split('^')[1]);
links.Add(lines[1].Split('^')[1]);
links.Add(lines[2].Split('^')[1]);
links.Add(lines[3].Split('^')[1]);
The debugging process shows no errors, what could i be doing wrong ?
I wonder if an exception is being caught and swallowed somewhere, since by the sounds of it the program doesn't crash it merely skips some code. In Visual Studio, go to Debug\Exceptions, tick all the Thrown boxes and try again. If my suspicion is correct, this will identify the problem.

How could the existence of pseudo debug strings cause a difference in functionality?

If I have these sprinkled throughout my code:
MessageBox.Show("See a format exception yet? #1");//todo: remove
(there are 7 of these, numbered from 1..7, most of which display (1,2,5,6,7))
I end up with one err msg ("Exception: Cannot find table 0 Location: frmFunction.SetPlatypus")
If I comment out all of those, I end up with a different err msg ("Exception: FormatException Location frmFunction.getDuckbillRecord")
How could this be? Shouldn't the existence/display of such an information msg have no effect on the way the code executes/the path it takes, etc.?
Note: getDuckbillRecord() is where all of the MessageBoxes are.
UPDATE
Using RT's suggestions as motivation, I came up with this:
public static StringBuilder LogMsgs = new StringBuilder();
public static void ExceptionHandler(Exception ex, string location)
{
try
{
LogMsgs.Append(string.Format("{0}\r\n", ex.Message)); //TODO: Comment out before deploying?
DateTime dt = DateTime.Now;
string timeAsStr = string.Format("{0}_{1}_{2}_{3}.txt", dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
using (StreamWriter file = new StreamWriter(timeAsStr))
{
file.WriteLine(LogMsgs.ToString());
}
. . .
//in the problematic code, replacing the MessageBox.Show() calls:
TTBT.LogMsgs.Append("Made it to location 1 in frmOverFunction.GetDuckbillRecord()\r\n");
...and it did help - the exception is reached right after the first of 7 "code waypoints," so there's something rotten in that particular Denmark, apparently.
UPDATE 2
After the rare experience of being able to run the app without crashing somewhere, I realized I also need that file-writing code in the main form's OnClosing() event - being in the global exception handler had worked for awhile - I wasn't expecting a clean termination of the app to ever occur again, I guess.
I'd strongly encourage you NOT to use MessageBox.Show(...) to log/trace/debug errors, because popping-up a dialog can introduce many subtle bugs and changes in behavior, focus, etc., especially if your UI flow/state is important.
Instead, use System.Diagnostics.Trace for writing tracing code (which you can optionally compile into your production/release code) or System.Diagnostics.Debug to write debug messages which get removed when you build your release version.
For example:
public void DoSomething(int a, int b)
{
Trace.TraceInformation("Starting to do something: a = {0}, b = {1}",
a, b);
try
{
int c = a / b;
}
catch (DivideByZeroException e)
{
Debug.WriteLine("OH NO ... 'b' WAS ZERO!!!! RUN AWAY!!!!");
throw e;
}
Trace.TraceInformation("Done doing something");
}
In the example above, the debug output will be available in debug builds, but will be removed in release builds. Trace output will be available in debug and retail bugs (unless you turn off the TRACE build parameter) but introduces no measurable perf impact unless you hook-up a listener and start writing trace output to a slow medium like spinning disks, ticker-tape printers, etc. ;)
When you run code with Trace and/or Debug builds with Debug messages in Visual Studio, the messages are written to the Output pane so you can watch what's going on inside your app as it runs.
If you want to, you can also write a stand-alone trace listener that listens for Trace and/or Debug messages and log them to a file/database or display them in a console window (or GUI if you want to get fancy).
You can also use tools like log4net which enables you to write log/trace messages to a variety of file formats, databases, etc.

Why would MessageBox.Show cause UnhandledException?

I am working on an app that uses location services. If I am debugging, the app works fine. If I start without debugging, on the first run (after rebuild), it crashes when asking for authorization to use location services. What happens is that if you let it sit, with the messagebox showing long enough (5-10 seconds), it crashes. If I start without debugging again, it works fine (though it doesn't show the messagebox again, because somehow it gets past that line to the next line AFTER the conditional statement, where it sets first run false (I assume, because it doesn't show again).
Again, if I am debugging, no problems. If I start without debugging, it dies. This is the case when building in either the Debug or Release modes.
If I comment this block of code out, it executes without a problem. If I click OK quickly, it executes without a problem.
if (settings.FirstRunLocationPermission)
{
string message = "Do you wish to use location services to see your location on the map? Your location is not being tracked. You can change this authorization in the settings.";
//if (MessageBox.Show(message,"authorization",MessageBoxButton.OKCancel) == MessageBoxResult.OK)
//{
// settings.AllowLocation = true;
//}
settings.FirstRunLocationPermission = false;
}
I would greatly appreciate it if anyone can explain to me why a simple messagebox checking for ok would cause a problem like this. Thanks!
Most likely you are showing the MessageBox in OnNavigatedTo. If that is the case, this SO answer should help. The problem is that if the user does not press a button your app will crash since the framework thinks that navigation has failed.
And yes, this behaviour occurs to me only when debugger is not attached.
If you look at the MSDN Documentation for the method, the reasons for the possible Exceptions is fairly clear:
MDSN - MessageBox.Show Method
The other possibility is that there is some code running in the setter for the settings.AllowLocation property that is throwing the Exception. It would help if you included the actual Exception being thrown.
I use it this way, and it works :
var msg = MessageBox.Show("Do you .... ?", "Title", MessageBoxButton.OKCancel);
if(msg == MessageBoxResult.OK)
{
//Do something;
}
Good luck

Categories

Resources