The length of the string is incorrect.

My colleague and I are debugging a problem in the WCF service in which it works, where the string length is not evaluated correctly. He uses this method for the unit test method in his WCF service:

// Unit test method public void RemoveAppGroupTest() { string addGroup = "TestGroup"; string status = string.Empty; string message = string.Empty; appActiveDirectoryServicesClient.RemoveAppGroup("AOD", addGroup, ref status, ref message); } // Inside the WCF service [OperationBehavior(Impersonation = ImpersonationOption.Required)] public void RemoveAppGroup(string AppName, string GroupName, ref string Status, ref string Message) { string accessOnDemandDomain = "MyDomain"; RemoveAppGroupFromDomain(AppName, accessOnDemandDomain, GroupName, ref Status, ref Message); } public AppActiveDirectoryDomain(string AppName, string DomainName) { if (string.IsNullOrEmpty(AppName)) { throw new ArgumentNullException("AppName", "You must specify an application name"); } } 

We tried to enter the .NET source code to find out what string.IsNullOrEmpty was received, but the IDE printed this message when we tried to evaluate the variable: "It is impossible to get the value of the local value or the argument" how "is not available in this instruction, maybe because it has been optimized. " (None of the projects involved included optimization). So, we decided to try to explicitly set the variable value inside the method itself just before checking the length, but this did not help.

 // Lets try this again. public AppActiveDirectoryDomain(string AppName, string DomainName) { // Explicitly set the value for testing purposes. AppName = "AOD"; if (AppName == null) { throw new ArgumentNullException("AppName", "You must specify an application name"); } if (AppName.Length == 0) { // This exception gets thrown, even though it obviously isn't a zero length string. throw new ArgumentNullException("AppName", "You must specify an application name"); } } 

We really pull our hair on it. Has anyone else experienced this behavior? Any tips on debugging it?


Here's the MSIL for the AppActiveDirectoryDomain object where the behavior occurs:

 .method public hidebysig specialname rtspecialname instance void .ctor(string AppName, string DomainName) cil managed { .maxstack 5 .locals init ( [0] class [System]System.Net.NetworkCredential ldapCredentials, [1] string[] creds, [2] string userName, [3] class [mscorlib]System.ArgumentNullException exc, [4] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.DirectoryContext directoryContext, [5] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.Domain domain, [6] class [System.DirectoryServices.Protocols]System.DirectoryServices.Protocols.LdapException V_6, [7] class [mscorlib]System.Exception V_7, [8] bool CS$4$0000, [9] char[] CS$0$0001, [10] string[] CS$0$0002) L_0000: ldarg.0 L_0001: ldsfld string [mscorlib]System.String::Empty L_0006: stfld string MyNamespace.MyClass.AppActiveDirectoryDomain::appOU L_000b: ldarg.0 L_000c: call instance void [mscorlib]System.Object::.ctor() L_0011: nop L_0012: nop L_0013: ldstr "AOD" L_0018: call bool [mscorlib]System.String::IsNullOrEmpty(string) L_001d: ldc.i4.0 L_001e: ceq L_0020: stloc.s CS$4$0000 L_0022: ldloc.s CS$4$0000 L_0024: brtrue.s L_0037 L_0026: nop L_0027: ldstr "AppName" L_002c: ldstr "You must specify an application name" L_0031: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string, string) L_0036: throw 

And MSIL to call string.IsNullOrEmpty :

 .method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: brfalse.s L_000d L_0003: ldarg.0 L_0004: callvirt instance int32 System.String::get_Length() L_0009: ldc.i4.0 L_000a: ceq L_000c: ret L_000d: ldc.i4.1 L_000e: ret } 

Edit:

Here is a screenshot of the variable in the Watch window at the time of throwing ArgumentNullException: http://imgur.com/xQm4J. PNG

In addition, a second screenshot showing the exception that occurs when checking the length of a string after explicitly declaring 5 lines above: http://imgur.com/lSrk9.png

Update # 3: We tried to change the name of the local variable and skipped the zero check and length check, but failed when we call string.IsNullOrEmpty . See this screenshot: http://imgur.com/Z57AA.png .


Answers:

  • We do not use any tools that could change MSIL. We performed a cleanup and manually deleted all the files from the assembly directories and forcefully restored ... the same result.

  • The following statement evaluates to true and is included in the if block: if (string.IsNullOrEmpty("AOD")) { /* */ } .

  • The constructor is called like this:

    try { using (AppActiveDirectoryDomain domain = new AppActiveDirectoryDomain(AppName, DomainName)) { } }

This is directly in the WCF service itself; AppName and DomainName are call parameters. Even bypassing these parameters and using new lines, we still get errors.


+7
string c # wcf
source share
3 answers

This turned out to be a 64-bit problem. Or at least this is only a problem with the 64-bit version. In IIS 7.0 on a 64-bit OS, by default, all web sites host 64-bit processes. If we install the service in a 32-bit process, the problem will disappear.

0
source share

I have 2 offers

  • Use ILDASM to take a look at the generated IL, perhaps place the IL here so that the community can see.

  • Change the argument name "AppName" to something completely different "xxxAppName", for example.

I know that point 2 may seem pointless, but in the past I have come across seemingly inexplicable situations, but found that something is not compiling or a conflict between areas, while the debugger shows what you expect. And, this does not hurt to try :)

+2
source share

Unfortunately, the code examples do not show where and how this failed constructor is called, i.e. where an object of type AppActiveDirectoryDomain . (Not that it matters, given the last code sample given.)

Speaking of which, I came across similar illogical problems in Visual Studio earlier when I was playing with Code Contracts (which overwrites the CIL instructions emitted by the compiler), and at other times for a random reason. I never found a true problem, I remember how I changed some code in a completely different place, and suddenly the problem was solved.

I suspect that sometimes the debugger somehow goes out of sync with the actual state of the program.

Some questions:

  • Do you use any tools that overwrite the CIL code (= MSIL) after starting the compiler? (e.g. Code Contracts or PostSharp)

  • Could it be that your debugger symbol files or program database are not in sync with the compiled code? Did you clean the project?

You can try the following:

  • Does the operator if ("AOD".Length == 0) throw new ArgumentNullException(...); an if ("AOD".Length == 0) throw new ArgumentNullException(...); only inside this particular constructor? Or the problem persists if you move this operator to the caller function? Does it persist if you move it, for example. to the Main() method?

  • Try using your code with a different debugger (links to another question in StackOverflow about MSIL debuggers) if you have one available.

+1
source share

All Articles