Тот же код IL, другой вывод - как это возможно?

У меня есть часть кода, который выводы различные результаты, в зависимости от компилятора C# и времени выполнения.

Рассматриваемый код:

using System;

public class Program {
    public static void Main() {
        Console.WriteLine(string.Compare("alo\0alo\0", "alo\0alo\0\0", false, System.Globalization.CultureInfo.InvariantCulture));
    }
}

Результаты:

                    Compiling with mono (gmcs)    Compiling with .Net (csc)
Running with mono                           -1                           -1
Running with .Net                           -1                            0

Как это может произвести различные значения при выполнении с платформой .NET?

(BTW, согласно http://msdn.microsoft.com/en-us/library/system.string.aspx, которым вывод должен быть 0, таким образом, ответ mono является неправильным, но это не связано с моим вопросом.)

Даже сгенерированный код IL является (почти) тем же.

Компиляция с .NET:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       29 (0x1d)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00 ) // a.l.o...a.l.o...
  IL_0006:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00   // a.l.o...a.l.o...
                                  00 00 ) 
  IL_000b:  ldc.i4.0
  IL_000c:  call       class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture()
  IL_0011:  call       int32 [mscorlib]System.String::Compare(string,
                                                              string,
                                                              bool,
                                                              class [mscorlib]System.Globalization.CultureInfo)
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_001b:  nop
  IL_001c:  ret
} // end of method Program::Main

Компиляция с моно:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  8
  IL_0000:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00 ) // a.l.o...a.l.o...
  IL_0005:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00   // a.l.o...a.l.o...
                                  00 00 ) 
  IL_000a:  ldc.i4.0
  IL_000b:  call       class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture()
  IL_0010:  call       int32 [mscorlib]System.String::Compare(string,
                                                              string,
                                                              bool,
                                                              class [mscorlib]System.Globalization.CultureInfo)
  IL_0015:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_001a:  ret
} // end of method Program::Main

Единственной разницей являются две дополнительных инструкции по NOP в версии .NET.

Как это возможно? Как эти два выходных значения могут отличаться?

Кроме того, если у кого-либо есть и .NET и моно установленный, можно ли воспроизвести его?

Править: Я не забочусь о том, что корректный результат, и я не забочусь, что моно и .NET приводит к различным результатам. Я никогда не буду, вероятно, встречаться встроенный, аннулирует, И отсортируйте их, И порядок сортировки будет важен.

Моя проблема состоит в том, что то же время выполнения (.Net 2.0) приводит к различным результатам при компиляции различными компиляторами.

РЕДАКТИРОВАНИЕ 2: Я добавил таблицу и попытался разъяснить вопрос, должно быть легче понять теперь.

9
задан Hali 11 May 2010 в 23:30
поделиться

5 ответов

Это связано с упорядочиванием строк? См. эту запись в блоге Марка

2
ответ дан 4 December 2019 в 23:38
поделиться

Моя догадка заключается в том, что когда вы компилируете его с помощью Mono, он ссылается на версию mscorlib .NET 2.0 - тогда как когда вы скомпилируйте его с помощью VS, он нацелен на .NET 4.0.

Я могу ошибаться в отношении того, какая именно версия является целевой в каждом случае, но я бы начал с этого: не смотрите на IL для метода, посмотрите на сборки, на которые есть ссылки.

(Может помочь, если вы скажете, какие версии VS, .NET и Mono у вас установлены, кстати.)

РЕДАКТИРОВАТЬ: Хорошо, если он делает то же самое, независимо от того, на какую версию вы нацеливаетесь , как насчет выполнения сравнения результатов запуска ildasm для каждой версии? Сравните файлы целиком, а не только IL для самого вызова метода.

3
ответ дан 4 December 2019 в 23:38
поделиться

Я думаю, что это просто еще одна несовместимость Mono с .NET (особенно в System.String::Compare при обработке информации о культуре), поэтому, пожалуйста, напишите отчет, чтобы сообщить команде Novell/Mono. Они смогут получить обратную связь и подтвердить, является ли это желаемым. Если это ошибка, вы будете знать, по крайней мере, когда она может быть исправлена.

http://www.mono-project.com/Bugs

1
ответ дан 4 December 2019 в 23:38
поделиться

Я предполагаю, что asm-команды nop (No Operation) предназначены для выравнивания команд в памяти. Это дает возможность процессору загружать код во внутренний кеш и, следовательно, запускать его быстрее. Это довольно стандартный метод оптимизации, и кажется, что компилятор .NET делает это, в то время как Mono это не волнует.

0
ответ дан 4 December 2019 в 23:38
поделиться

Сравнение строк определяется параметром CultureInfo.CompareInfo . Я предполагаю, что CultureInfo.CompareInfo возвращает разные битовые маски в .Net и Mono. .Net 3.5 возвращает 0xff , когда я печатаю System.Globalization.CultureInfo.InvariantCulture.CompareInfo . Что печатается в монохромном режиме? Сравните недостающие биты с System.Globalization.CultureInfo.CompareOptions . Если битовые маски одинаковы, значит, в Mono или .Net есть ошибка в интерпретации информации о культуре.

Имея это в виду, я бы очень не хотел, чтобы в вашем коде была какая-либо заметная разница, если дизассемблирование будет таким же.

0
ответ дан 4 December 2019 в 23:38
поделиться
Другие вопросы по тегам:

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