Domanda

In un C # costruttore, che finisce con una chiamata a this(...), la chiamata effettiva viene tradotto a questo:

0000003d  call        dword ptr ds:[199B88E8h]

Qual è il registro DS contenuti qui? So che è il segmento di dati, ma è questa chiamata attraverso un VMT-tavolo o simili? Ne dubito, però, dal momento che this(...) non sarebbe una chiamata a un metodo virtuale, solo un altro costruttore.

Lo chiedo perché il valore in quella posizione sembra essere un male in qualche modo, se ho colpito F11, traccia in (Visual Studio 2008), in quel call-istruzione, il programma si blocca con una violazione di accesso.

Il codice è profondo all'interno di una libreria di controllo 3rd party, dove, anche se ho il codice sorgente, non ho gli assembly compilati con le informazioni di debug sufficiente che posso rintracciarlo tramite codice C #, solo attraverso la disassembler, e allora devo corrispondere a quello nuovo al codice vero e proprio.

Il codice C # in questione è questo:

public AxisRangeData(AxisRange range) : this(range, range.Axis) {
}

Reflector mi mostra questo codice IL:

.maxstack 8
L_0000: ldarg.0 
L_0001: ldarg.1 
L_0002: ldarg.1 
L_0003: callvirt instance class DevExpress.XtraCharts.AxisBase DevExpress.XtraCharts.AxisRange::get_Axis()
L_0008: call instance void DevExpress.XtraCharts.Native.AxisRangeData::.ctor(class DevExpress.XtraCharts.ChartElement, class DevExpress.XtraCharts.AxisBase)
L_000d: ret 

E 'che lì ultima chiamata, l'altro costruttore della stessa classe, che non riesce. Il debugger mai superfici dentro l'altro metodo, appena si blocca.

Lo smontaggio per il metodo dopo JITting è questo:

00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  sub         esp,14h 
00000006  mov         dword ptr [ebp-4],ecx 
00000009  mov         dword ptr [ebp-8],edx 
0000000c  cmp         dword ptr ds:[18890E24h],0 
00000013  je          0000001A 
00000015  call        61843511 
0000001a  mov         eax,dword ptr [ebp-4] 
0000001d  mov         dword ptr [ebp-0Ch],eax 
00000020  mov         eax,dword ptr [ebp-8] 
00000023  mov         dword ptr [ebp-10h],eax 
00000026  mov         ecx,dword ptr [ebp-8] 
00000029  cmp         dword ptr [ecx],ecx 
0000002b  call        dword ptr ds:[1889D0DCh]   // range.Axis
00000031  mov         dword ptr [ebp-14h],eax 
00000034  push        dword ptr [ebp-14h] 
00000037  mov         edx,dword ptr [ebp-10h] 
0000003a  mov         ecx,dword ptr [ebp-0Ch] 
0000003d  call        dword ptr ds:[199B88E8h]   // this(range, range.Axis)?
00000043  nop              
00000044  mov         esp,ebp 
00000046  pop         ebp  
00000047  ret              

In pratica quello che sto chiedendo è questo:

  • Quale lo scopo del indirezione ds:[ADDR] qui? VMT-tabella è solo per virtuale non è vero? e questo è il costruttore
  • Può il costruttore devono ancora essere JITted, che potrebbe significare che la chiamata sarebbe in realtà chiamata attraverso uno spessore JIT? Ho paura che sono in acque profonde qui, quindi tutto potrebbe e potrebbe aiutare.

Modifica :. Beh, il problema solo peggiorata, o meglio, o qualsiasi altra cosa

Stiamo sviluppando la funzionalità .NET in un progetto C # in uno Studio 2008 soluzione di Visual, e il debug e lo sviluppo tramite Visual Studio.

Tuttavia, alla fine, questo codice verrà caricato in un runtime .NET ospitato da un'applicazione di Win32 Delphi.

Al fine di facilitare la sperimentazione di tali caratteristiche, possiamo anche configurare il progetto di Visual Studio / soluzione / debugger per copiare i prodotti dll alla directory di Delphi applicazione, e quindi eseguire l'applicazione Delphi, attraverso il debugger di Visual Studio.

Si scopre che il problema va via se corro il programma all'esterno del debugger, ma durante il debug, si pota in su, ogni volta.

Non è sicuro che aiuta, ma dal momento che il codice non è previsto per il rilascio in produzione per altri 6 mesi o giù di lì, quindi ci vuole un po 'la pressione di esso per il rilascio di test che abbiamo presto.

mi tuffo nelle parti della memoria in seguito, ma probabilmente non fino a quando durante il fine settimana, e posta un follow-up.

È stato utile?

Soluzione

segmento dati è dove i compilatori di solito mettere le variabili globali e in cui risiede l'Import Address Table.

00000029  cmp         dword ptr [ecx],ecx 
0000002b  call        dword ptr ds:[1889D0DCh]

La prima riga è in realtà un null-controllo, che alla fine solleva un NullReferenceException se il puntatore si trova nel registro ECX è valido.

L'istruzione MSIL callvirt deve fare il null controllo prima di richiamare il metodo effettivo. Detto questo, possiamo tranquillamente assumere che queste due righe di codice assembly hanno la seguente rappresentazione codice MSIL:

class DevExpress.XtraCharts.AxisBase DevExpress.XtraCharts.AxisRange::get_Axis()

E il codice assembly commentato:

00000026  mov         ecx,dword ptr [ebp-8]      // store the pointer to the 'range' in ECX
00000029  cmp         dword ptr [ecx],ecx        // null-check
0000002b  call        dword ptr ds:[1889D0DCh]   // range.get_Axis()
00000031  mov         dword ptr [ebp-14h],eax    // store the result in a local variable
00000034  push        dword ptr [ebp-14h]        // push the result onto a stack
00000037  mov         edx,dword ptr [ebp-10h]    // this variable was previously loaded with the 'range' pointer
0000003a  mov         ecx,dword ptr [ebp-0Ch]    // here seems to be stored the actual 'this' pointer
0000003d  call        dword ptr ds:[199B88E8h]   // call the this(...) ctor

Non è chiaro per me perché è crash, hai provato guardando il contenuto della locazione di memoria (DS:[199B88E8h])?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top