Note that there are some explanatory texts on larger screens.

plurals
  1. POString Length Evaluating Incorrectly
    primarykey
    data
    text
    <p>My coworker and I are debugging an issue in a WCF service he's working on where a string's length isn't being evaluated correctly. He is running this method to unit test a method in his WCF service:</p> <pre><code>// 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"); } } </code></pre> <p>We tried to step into the .NET source code to see what value <code>string.IsNullOrEmpty</code> was receiving, but the IDE printed this message when we attempted to evaluate the variable: 'Cannot obtain value of local or argument 'value' as it is not available at this instruction pointer, possibly because it has been optimized away.' (None of the projects involved have optimizations enabled). So, we decided to try explicitly setting the value of the variable inside the method itself, immediately before the length check -- but that didn't help.</p> <pre><code>// 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"); } } </code></pre> <p>We're really pulling our hair out on this one. Has anyone else experienced behavior like this? Any tips on debugging it?</p> <hr> <p>Here's the MSIL for the <code>AppActiveDirectoryDomain</code> object, where the behavior is occuring:</p> <pre><code>.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 </code></pre> <p>And the MSIL for the <code>string.IsNullOrEmpty</code> call:</p> <pre><code>.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 } </code></pre> <hr> <p><strong>Edit:</strong></p> <p>Here is a screenshot of the variable in the 'Watch' window at the moment the ArgumentNullException is thrown: <a href="https://imgur.com/xQm4J.png" rel="nofollow noreferrer">http://imgur.com/xQm4J.png</a></p> <p>Also, a second screenshot showing the exception being thrown when checking the length of the string, after explicitly declaring it 5 lines above: <a href="https://imgur.com/lSrk9.png" rel="nofollow noreferrer">http://imgur.com/lSrk9.png</a></p> <p>Update #3: We tried changing the name of the local variable and it passes the null check and the length check, but fails when we call <code>string.IsNullOrEmpty</code>. See this screenshot: <a href="https://imgur.com/Z57AA.png" rel="nofollow noreferrer">http://imgur.com/Z57AA.png</a>.</p> <hr> <p><strong>Responses:</strong></p> <ul> <li><p>We don't use any tools that would modify the MSIL. We've performed a cleanup, and also manually deleted all files from the build directories, and forced a rebuild... same outcome.</p></li> <li><p>The following statement evaluates as true and enters the if block: <code>if (string.IsNullOrEmpty("AOD")) { /* */ }</code>.</p></li> <li><p>The constructor is called like so:</p> <p><code>try { using (AppActiveDirectoryDomain domain = new AppActiveDirectoryDomain(AppName, DomainName)) { } }</code></p></li> </ul> <p>This is immediately within the WCF service method itself; AppName and DomainName are parameters to the call. Even bypassing these parameters and using new strings, we still get the errors.</p> <hr>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload