Длина строки, оценивающая неправильно

Мой коллега и я отлаживаем проблему в сервисе WCF, он продолжает работать, где длина строки не оценивается правильно. Он выполняет этот метод к модульному тесту метод в его сервисе WCF:

// 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");
    }
}

Мы пытались ступить в исходный код.NET для наблюдения что значение string.IsNullOrEmpty получал, но IDE распечатал это сообщение, когда мы попытались оценить переменную: 'Не может получить значение локальных или аргумента 'значение', поскольку это не доступно в этом указателе команд, возможно потому что это было оптимизировано далеко'. (Ни одному из включенных проектов не включили оптимизацию). Так, мы решили попытаться явно установить значение переменной в самом методе, сразу перед проверкой длины - но это не помогло.

// 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");
    }
}

Мы действительно вытаскиваем волосы на этом. Кто-либо еще испытал поведение как это? Какие-либо подсказки относительно отладки его?


Вот MSIL для AppActiveDirectoryDomain объект, где поведение происходит:

.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

И MSIL для 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 
}

Править:

Вот снимок экрана переменной в окне 'Watch' в данный момент, ArgumentNullException брошен: http://imgur.com/xQm4J.png

Кроме того, второй снимок экрана, показывающий исключение, выданное при проверке длины строки, после явного объявления его 5 строк выше: http://imgur.com/lSrk9.png

Обновление № 3: Мы пытались менять имя локальной переменной, и это проходит пустую проверку и проверку длины, но перестало работать, когда мы звоним string.IsNullOrEmpty. См. этот снимок экрана: http://imgur.com/Z57AA.png.


Ответы:

  • Мы не используем инструментов, которые изменили бы MSIL. Мы выполнили очистку, и также вручную удалили все файлы из каталогов сборки и вызвали восстанавливание... того же результата.

  • Следующее утверждение оценивает как верное и входит если блок: if (string.IsNullOrEmpty("AOD")) { /* */ }.

  • Как конструктор вызывают так:

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

Это сразу в рамках самого сервисного метода WCF; AppName и DomainName являются параметрами к вызову. Даже обходя эти параметры и использование новых строк, мы все еще получаем ошибки.


7
задан Justin Rusbatch 30 April 2010 в 18:45
поделиться

3 ответа

Оказалось, что это проблема 64-битной версии. Или, по крайней мере, это проблема только для 64-битных ОС. В IIS 7.0 на 64-битной ОС все веб-сайты по умолчанию размещаются в 64-битных процессах. Если мы настроим службу на размещение в 32-битном процессе, проблема исчезнет.

0
ответ дан 7 December 2019 в 16:40
поделиться

У меня есть 2 предложения

  1. Используйте ILDASM, чтобы взглянуть на генерируемый IL, возможно, опубликуйте IL здесь, чтобы сообщество могло взглянуть

  2. Измените имя аргумента 'AppName' на что-то совсем другое 'xxxAppName', например.

Я знаю, что пункт 2 может показаться бессмысленным, но в прошлом я сталкивался с необъяснимыми на первый взгляд ситуациями, когда выяснялось, что что-то не компилируется или существует конфликт областей видимости, в то время как отладчик показывает то, что вы ожидаете. Да и попробовать не помешает :)

2
ответ дан 7 December 2019 в 16:40
поделиться

К сожалению, в ваших примерах кода не показано, где и как вызывается этот конструктор с ошибкой, т.е. где создается объект типа AppActiveDirectoryDomain . (Не то чтобы это имело значение, учитывая последний пример кода, который вы предоставили.)

При этом я уже сталкивался с подобными нелогичными проблемами в Visual Studio раньше, однажды, когда играл с Code Contracts (который переписывает CIL инструкции, исходящие из компилятора) и в другой раз по случайной причине. Я так и не нашел истинной проблемы, я помню, как изменил какой-то код в совершенно другом месте, и внезапно проблема была решена.

Я подозреваю, что иногда отладчик каким-то образом не синхронизируется с фактическим состоянием программы.

Некоторые вопросы:

  • Используете ли вы какие-либо инструменты, которые переписывают код CIL (= MSIL) после запуска компилятора? (например, Code Contracts или PostSharp)

  • Может быть, ваши файлы символов отладчика или база данных программы не синхронизированы с скомпилированным кодом? Вы выполнили очистку проекта?

Вы можете попробовать следующее:

  • Выдает ли оператор if ("AOD" .Length == 0) новое исключение ArgumentNullException (...); только бросать внутрь этого конкретного конструктора? Или проблема не исчезнет, ​​если вы переместите этот оператор в вызывающую функцию? Он все еще сохраняется, если вы его переместите, например. к методу Main () ?

  • Попробуйте использовать свой код с другим отладчиком ( ссылки на другой вопрос в StackOverflow об отладчиках MSIL ), если у вас есть один доступен.

1
ответ дан 7 December 2019 в 16:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: