Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

352
Views
¿Por qué el comportamiento del código es diferente en el modo de liberación y depuración?

Considere el siguiente código:

 private static void Main(string[] args) { var ar = new double[] { 100 }; FillTo(ref ar, 5); Console.WriteLine(string.Join(",", ar.Select(a => a.ToString()).ToArray())); } public static void FillTo(ref double[] dd, int N) { if (dd.Length >= N) return; double[] Old = dd; double d = double.NaN; if (Old.Length > 0) d = Old[0]; dd = new double[N]; for (int i = 0; i < Old.Length; i++) { dd[N - Old.Length + i] = Old[i]; } for (int i = 0; i < N - Old.Length; i++) dd[i] = d; }

El resultado en el modo de depuración es: 100,100,100,100,100. Pero en modo Release es: 100,100,100,100,0.

¿Qué está pasando?

Se probó con .NET Framework 4.7.1 y .NET Core 2.0.0.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Esto parece ser un error JIT; He probado con:

 // ... existing code unchanged for (int i = 0; i < N - Old.Length; i++) { // Console.WriteLine(i); // <== comment/uncomment this line dd[i] = d; }

y agregar Console.WriteLine(i) lo soluciona. El único cambio de IL es:

 // ... L_0040: ldc.i4.0 L_0041: stloc.3 L_0042: br.s L_004d L_0044: ldarg.0 L_0045: ldind.ref L_0046: ldloc.3 L_0047: ldloc.1 L_0048: stelem.r8 L_0049: ldloc.3 L_004a: ldc.i4.1 L_004b: add L_004c: stloc.3 L_004d: ldloc.3 L_004e: ldarg.1 L_004f: ldloc.0 L_0050: ldlen L_0051: conv.i4 L_0052: sub L_0053: blt.s L_0044 L_0055: ret

contra

 // ... L_0040: ldc.i4.0 L_0041: stloc.3 L_0042: br.s L_0053 L_0044: ldloc.3 L_0045: call void [System.Console]System.Console::WriteLine(int32) L_004a: ldarg.0 L_004b: ldind.ref L_004c: ldloc.3 L_004d: ldloc.1 L_004e: stelem.r8 L_004f: ldloc.3 L_0050: ldc.i4.1 L_0051: add L_0052: stloc.3 L_0053: ldloc.3 L_0054: ldarg.1 L_0055: ldloc.0 L_0056: ldlen L_0057: conv.i4 L_0058: sub L_0059: blt.s L_0044 L_005b: ret

que se ve exactamente bien (la única diferencia es el ldloc.3 adicional y la call void [System.Console]System.Console::WriteLine(int32) , y un objetivo diferente pero equivalente para br.s ).

Necesitará una solución JIT, sospecho.

Ambiente:

  • Environment.Version : 4.0.30319.42000
  • <TargetFramework>netcoreapp2.0</TargetFramework>
  • VS: 15.5.0 Vista previa 5.0
  • dotnet --version : 2.1.1
over 4 years ago · Santiago Trujillo Report

0

Efectivamente es un error de montaje. x64, .net 4.7.1, compilación de lanzamiento.

desmontaje:

 for(int i = 0; i < N - Old.Length; i++) 00007FF942690ADD xor eax,eax for(int i = 0; i < N - Old.Length; i++) 00007FF942690ADF mov ebx,esi 00007FF942690AE1 sub ebx,ebp 00007FF942690AE3 test ebx,ebx 00007FF942690AE5 jle 00007FF942690AFF dd[i] = d; 00007FF942690AE7 mov rdx,qword ptr [rdi] 00007FF942690AEA cmp eax,dword ptr [rdx+8] 00007FF942690AED jae 00007FF942690B11 00007FF942690AEF movsxd rcx,eax 00007FF942690AF2 vmovsd qword ptr [rdx+rcx*8+10h],xmm6 for(int i = 0; i < N - Old.Length; i++) 00007FF942690AF9 inc eax 00007FF942690AFB cmp ebx,eax 00007FF942690AFD jg 00007FF942690AE7 00007FF942690AFF vmovaps xmm6,xmmword ptr [rsp+20h] 00007FF942690B06 add rsp,30h 00007FF942690B0A pop rbx 00007FF942690B0B pop rbp 00007FF942690B0C pop rsi 00007FF942690B0D pop rdi 00007FF942690B0E pop r14 00007FF942690B10 ret

El problema está en la dirección 00007FF942690AFD, el jg 00007FF942690AE7. Salta hacia atrás si ebx (que contiene 4, el valor final del ciclo) es más grande (jg) que eax, el valor i. Esto falla cuando es 4, por supuesto, por lo que no escribe el último elemento en la matriz.

Falla, porque aumenta el valor del registro de i (eax, en 0x00007FF942690AF9), y luego lo verifica con 4, pero aún tiene que escribir ese valor. Es un poco difícil identificar dónde se encuentra exactamente el problema, ya que parece que podría ser el resultado de la optimización de (N-Old.Length), ya que la compilación de depuración contiene ese código, pero la compilación de lanzamiento lo calcula previamente. Así que eso es para que lo arregle la gente jit;)

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!