Actually I like these issues and solve them then with ETW Tracing (most of the time). E.g. AV Scanners can cause funny issues which can make software fail in interesting ways. [^]
Alois Kraus
Posts
-
What's your least favorite part of coding? -
Obscure paths to serious bugsI have received a perf issue that a machine was unusable due to a schtasks.exe consuming all CPU. When looking at the MiniDump I did only see garbage stack traces. Ok send me a full dump but the stacks were still ending in heap allocated memory which is strange for a process not having dynamic code generation. When checking which code the many threads did execute I found highly optimized AVX2 assembly and unusal assembly instructions such as aesenc and related. These instructions are only known to guys creating cryptographic algos with the Intel AES-NI instructions to speed up AES encryption. After counting the possibilities I did suspect that a Trojan was just encrypting that machine. That turned from a perf issue to a really serious problem. With Windbg and the mex extension I could save the exe to disk which my AV Scanner would after a few seconds delete because it has detected malicious software. This helped to find out what it actually was. In this case it was a Monero miner. Ok it was not encrypting the disk but still a bad issue which needs to some cleaning of that machine. My colleagues still ask me to write a book about such stuff.
-
try-catch code convention [modified]Sounds familar :) Perhaps you should add at least some tracing to your methods like this one Then your code would be transparent to exceptions but you can still see what exceptions did flow through your code without becoming much slower.
public void Demo\_Show\_Leaving\_Trace\_With\_Exception() { TracerConfig.Reset("console"); SomeMethod(); } void SomeMethod() { using (Tracer t = new Tracer(myType, "SomeMethod")) { SomeOtherMethod(); } } private void SomeOtherMethod() { using (Tracer t = new Tracer(myType, "SomeOtherMethod")) { FaultyMethod(); } } private void FaultyMethod() { throw new NotImplementedException("Hi this a fault"); }
The output would look the like this: 18:57:46.665 03064/05180 <{{ > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod 18:57:46.668 03064/05180 <{{ > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod 18:57:46.670 03064/05180 < }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Exception thrown: System.NotImplementedException: Hi this a fault at ApiChange.IntegrationTests.Diagnostics.TracingTests.FaultyMethod() at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod() at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod() at ApiChange.IntegrationTests.Diagnostics.TracingTests.Demo_Show_Leaving_Trace_With_Exception() 18:57:46.670 03064/05180 < }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Duration 2ms 18:57:46.689 03064/05180 < }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod Duration 24ms That is a great time saver to find out where some exception did come from without the need to type try/catch(Exception ex) { LogException(ex);throw; } in many methods to find out where some exception did go through. Yours, Alois Kraus
-
Parallelizing code the easy (er) wayThe ApiChange tool has a nice Api built upon it with full excepiton handling and other goodies. The base class is WorkItemDispatcher where you can send work via a queue to the thread pool while you can limit the maximum concurrent threads to some value. WorkItemDispatcher.cs In the unit tests are some examples how this thing can be used. WorkItemDispatcherTests.cs I did need it to concurrently read files from n threads but not at the same time since the hard disc would drop dead if 500 threds would read 500 different files in parallel. Did you know about the ApicChange tool? Perhaps I will write an article about that one as well :) More info about this can be found here: http://geekswithblogs.net/akraus1/Default.aspx Yours, Alois Kraus
-
A horror in release codeI guess the message was "Drive not A not Ready" from crss.exe. The reason for that is simple. You have in your application somewhere a drive letter selection combo box. That little snippet should exhibit this problem: foreach (DriveInfo d in DriveInfo.GetDrives()) { Console.WriteLine("Root: {0}", d.RootDirectory); } All you have to do is to check the DriveType if it is removeable and skip it altogether. If you do not access it then you wont have any problems with drive not ready messages. Yours, Alois Kraus
-
Logging trouble [modified]I guess you have no reflection permission over private members in your web service since you normally run under medium trust. private static void WriteEntry the Stackwalk stackTrace = new StackTrace(); stackFrame = stackTrace.GetFrame(2); over your method will cause exceptions. Yours, Alois Kraus
-
Bad use of ASSERT...PJ Arends wrote:
Release builds are just faulty and should never, ever be used.
Are you waiting for someone to take this statement serious to start a flame war? ;P Yours, Alois Kraus
-
The true advantage of C# over C++No. C# is natural elegance ;-)
-
Stream ReaderThis is a lifetime issue because the underlying stream has been finalized before the StreamReader was flushed. This article should help you to get more light into this issue: http://geekswithblogs.net/akraus1/articles/81629.aspx Yours, Alois Kraus
-
Building stringsIf you have to alter very big strings StringBuilder is the way to go. But for small strings the border where StringBuilder is faster than the String.xxx functions becomes a moving target: http://www.codeproject.com/useritems/StringBuilder_vs_String.asp Yours, Alois Kraus
-
Evil for loopYou are right that the code posted here was simplified. I have posted it to demonstrate this specific problem. The loop was needed but this variable hoisting optimization did ruin my day. Yours, Alois Kraus
-
Evil for loopI agree. But I must also add: NEVER refactor when not ALL Unit Tests are green. Failing to do so will get you into the bad habit that some test are ok to fail and you miss the new important failed test case.
-
Evil for loopI did some refactoring of some older code and came across this snippet:
std::string str("This is a test str"); for(int i=str.length()-1;i>=0;i--) { printf("Examining char %d",i); }
The compiler complained about this with a warning: warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data Being a fan of zero compiler warnings I did give him what he wanted and changed the type of i from int to size_t. Ok it compiles now without any warnings but this change broke many applications during runtime. I was the bad guy of the week because this change was made in a low level library. -
Static constructors in C# will be the death of meHi Chris, sorry to hear you cursing against C#. You are right that there is no way to initialize statics during application startup. But this was never the case even in C++ days. In dlls there is an initialization chain which ensures that during module load the statics are intialized correctly. Things are different with JITed languages since most of the code has not been compiled when the module is loaded. This implies that there is no way to get your static initialized during module load except the CLR guys provide you with a hook to call your C#DllMain. But until then there will be no way initialize all statics during module load at once. From a more distant viewpoint it might even be a good thing that there is no such function anyway. If it would be here I hear you already cursing that you want to do something before C#DllMain was called ;) Your seconds problem that the static ctor aka type initializer has not been called when you are inside a static method should not happen except in grave cirumstances when a race condition occured. Suppose two classes A and B where each of them has a static instance of the other type inside it. This was bad design in C++ and is still in C#. If you have a different scenario where this happens I would be glad to hear about it. Yours, Alois Kraus My Blog
-
Static constructors in C# will be the death of meTo get the definitive answer when static ctor (or type initializers) do run here is the blog about it: http://geekswithblogs.net/akraus1/articles/90803.aspx Static ctors are thread safe they are normally called before any static method or field is accessed. This "normally" rule is broken in certain cases to ensure that the initialization sequence does not end up in recursion or a deadlock. Chris I supose you do have a class with statics and circular dependencies if you do not see your static ctor run before first access to your class. This is bad design ;P and should be avoided in favor of a more explicit initialization semantics like the double checked lock pattern. Yours, Alois Kraus
-
Exception handling in .NETStatic code analyzers like Reflector (it has a very good API but nearly no docu) can do this to a certain degree. You will never get 100% coverage since today software is plugable/configurable. There is no way to find out what module you did configure into you software. But for a good overview if some big holes are missed static code analyzers (FXCop should also be able to do this to a certain extent) they are surely useful. Yours, Alois Kraus
-
Exception handling in .NETYes there is a rationale behind this. Anders Hejlsberg (Turbo Pascal inventor, Delphi Lead Architect at Borland and now lead C# architect at MS) does explain why Javas checked exceptions are a nice concept but do break in big projects. http://www.artima.com/intv/handcuffs.html HTH, Alois Kraus
-
Why gravity is so weakThe book The Elegant Universe by Brian Greene is a very good one for the more simple minded of us (although I recomend still a university degree in nuclear physics to understand most of it). It covers all up to date theories especially the string theories (yes there is more than one around). He explains things in a very clear way without any formulas (ok in the appendix are a few ones). Nonetheless the ideas presented there show clearly that our universe is not so simple as many of us may think. Amazon
-
Big Problem with multicasting.Your net mask seems to be very odd. are you sure you want 224.0.0.0 as net mask for all your connections. Keep also in mind that the network metric is 1 for all your connections. This number is used to decide which connection to choose if several routes are possible the route with the least metric number will be used.
-
ISAPI filter -> ODBC -> Sybase connection problemYou should do your init work in HttpFilterProc. MSDN notes that it is dangerous to load any libraries in the DllMain function and .... Warning On attach, the body of your DLL entry-point function should perform only simple initialization tasks, such as setting up thread local storage (TLS), creating objects, and opening files. You must not call LoadLibrary in the entry-point function, because you may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code. Similarly, you must not call the FreeLibrary function in the entry-point function on detach, because this can result in a DLL being used after the system has executed its termination code. Calling functions other than TLS, object-creation, and file functions may result in problems that are difficult to diagnose. For example, calling User, Shell, COM, RPC, and Windows Sockets functions (or any functions that call these functions) can cause access violation errors, because their DLLs call LoadLibrary to load other system components. While it is acceptable to create synchronization objects in DllMain, you should not perform synchronization in DllMain (or a function called by DllMain) because all calls to DllMain are serialized. Waiting on synchronization objects in DllMain can cause a deadlock. To provide more complex initialization, create an initialization routine for the DLL. You can require applications to call the initialization routine before calling any other routines in the DLL. Otherwise, you can have the initialization routine create a named mutex, and have each routine in the DLL call the initialization routine if the mutex does not exist. Hope this helps