Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, Windows hata ayıklama araçlarıyla C++ ifade söz dizimi kullanımı açıklanmaktadır.
Hata ayıklayıcı iki farklı türde sayısal ifade kabul eder: C++ ifadeleri ve Microsoft Makro Derleyicisi (MASM) ifadeleri. Bu ifadelerin her biri, giriş ve çıkış için kendi söz dizimi kurallarına uyar.
Her bir söz dizimi türünün ne zaman kullanıldığı hakkında daha fazla bilgi için bkz. İfadeleri değerlendirme ve evaluate ifadesini değerlendirme komutu.
C++ ifade ayrıştırıcısı tüm C++ ifade söz dizimini destekler. Söz dizimi işaretçiler, kayan nokta sayıları ve diziler dahil olmak üzere tüm veri türlerini ve tüm C++ birli ve ikili işleçleri içerir.
Hata ayıklayıcıdaki watch ve Locals pencereleri her zaman C++ ifade değerlendiricisini kullanır.
Aşağıdaki örnekte C++ ifadesini değerlendir komutu talimat işaretçisi yazmacının değerini görüntüler.
0:000> ?? @eip
unsigned int 0x771e1a02
Yapıların boyutunu belirlemek için C++ sizeof işlevini kullanabiliriz.
0:000> ?? (sizeof(_TEB))
unsigned int 0x1000
İfade değerlendiricisini C++ olarak ayarlama
Varsayılan ifade değerlendiricisini görmek ve C++ olarak değiştirmek için .expr choose ifadesi değerlendiricisini kullanın.
0:000> .expr
Current expression evaluator: MASM - Microsoft Assembler expressions
0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions
Varsayılan ifade değerlendirici değiştirildikten sonra, C++ ifadelerini görüntülemek için ? evaluate ifadesi komutu kullanılabilir. Aşağıdaki örnek, komut işaretçisi yazmacının değerini görüntüler.
0:000> ? @eip
Evaluate expression: 1998461442 = 771e1a02
Yazmaç @eip başvurusu hakkında daha fazla bilgi edinmek için Yazmaç söz dizimi'ne bakın.
Bu örnekte, 0xD onaltılık değeri eip yazmacına eklenir.
0:000> ? @eip + 0xD
Evaluate expression: 1998461455 = 771e1a0f
C++ ifadelerinde yazmaçlar ve sahte yazmaçlar
C++ ifadeleri içinde yazmaçları ve sahte yazmaçları kullanabilirsiniz. @ işareti, yazmaç veya sahte kayıt öncesinde eklenmelidir.
İfade değerlendiricisi uygun atamayı otomatik olarak gerçekleştirir. Gerçek yazmaçlar ve tamsayı değeri olan sahte yazmaçlar, ULONG64 tipine dönüştürülür. Tüm adresler PUCHAR'a atanır, $threadETHREAD*'ya atanır, $procEPROCESS*'e atanır, $tebTEB*'ya atanır ve $pebPEB*'e atanır.
Bu örnekte TEB görüntülenir.
0:000> ?? @$teb
struct _TEB * 0x004ec000
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : (null)
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : (null)
+0x02c ThreadLocalStoragePointer : 0x004ec02c Void
+0x030 ProcessEnvironmentBlock : 0x004e9000 _PEB
+0x034 LastErrorValue : 0xbb
+0x038 CountOfOwnedCriticalSections : 0
Atama veya yan etki operatörü ile bir yazmaç veya sahte yazmaç değiştiremezsiniz. Bu değerleri değiştirmek için r registers komutunu kullanmanız gerekir.
Aşağıdaki örnek sahte kaydı 5 değerine ayarlar ve ardından görüntüler.
0:000> r $t0 = 5
0:000> ?? @$t0
unsigned int64 5
Yazmaçlar ve sahte yazmaçlar hakkında daha fazla bilgi için bkz . Yazmaç söz dizimi ve Sahte kayıt söz dizimi.
C++ ifadelerindeki sayılar
C++ ifadelerindeki sayılar, başka bir şekilde belirtmediğiniz sürece ondalık sayılar olarak yorumlanır. Onaltılık tamsayı belirtmek için, sayıdan önce 0x ekleyin. Sekizli tamsayı belirtmek için, sayıdan önce 0 (sıfır) ekleyin.
Varsayılan hata ayıklayıcısı radiksi, C++ ifadelerini girme yönteminizi etkilemez. BIR MASM ifadesini C++ ifadesi içinde iç içe geçirme dışında, ikili bir sayıyı doğrudan giremezsiniz.
xxxxx'xxxx biçiminde onaltılık 64 bitlik bir değer girebilirsiniz. Ayrıca, aksan (') işaretinden de atlayabilirsiniz. Her iki biçim de aynı değeri üretir.
L, U ve I64 son eklerini tamsayı değerleriyle kullanabilirsiniz. Oluşturulan sayının gerçek boyutu, son eke ve girdiğiniz sayıya bağlıdır. C++ dili başvuru kaynağına bakınız, bu yorum hakkında daha fazla bilgi için.
C++ ifade değerlendiricisinin çıkışı , C++ ifade kurallarının belirttiği veri türünü tutar. Ancak, bu ifadeyi bir komut için bağımsız değişken olarak kullanırsanız, her zaman bir dönüştürme yapılır. Örneğin, komut bağımsız değişkenlerinde adres olarak kullanıldıklarında işaretçilere tamsayı değerleri atamanız gerekmez. İfadenin değeri geçerli olarak bir tamsayıya veya işaretçiye atanamıyorsa, söz dizimi hatası oluşur.
Bazı çıkışlar için (ondalık) ön ekini 0n kullanabilirsiniz, ancak bunu C++ ifade girişi için kullanamazsınız.
C++ ifadelerindeki karakterler ve dizeler
Karakteri tek tırnak işaretiyle (') çevreleyerek girebilirsiniz. Standart C++ kaçış karakterlerine izin verilir.
Dize değişmez değerlerini çift tırnak işaretiyle (") çevreleyerek girebilirsiniz. \" öğesini böyle bir dize içinde kaçış dizisi olarak kullanabilirsiniz. Ancak, dizelerin ifade değerlendiricisi için bir anlamı yoktur.
C++ ifadelerindeki simgeler
Bir C++ ifadesinde, her simge türüne göre yorumlanır. Simgenin başvurduğu şeye bağlı olarak, bir tamsayı, veri yapısı, işlev işaretçisi veya başka bir veri türü olarak yorumlanabilir. C++ ifadesinde değiştirilmemiş modül adı gibi C++ veri türüne karşılık gelmeyen bir simge kullandığınızda bir söz dizimi hatası oluşur.
Simge adından önce bir modül adı ve ünlem işareti eklerseniz, simge adından büyük vurgu (') veya kesme işareti (') kullanabilirsiniz. Bir şablon adından sonra < ve > sınırlayıcılarını eklediğinizde, bu sınırlayıcılar arasına boşluk ekleyebilirsiniz.
Simge belirsiz olabilirse, simgeden önce bir modül adı ve ünlem işareti (!) veya yalnızca ünlem işareti ekleyebilirsiniz. Bir simgenin yerel olması gerektiğini belirtmek için modül adını atlayın ve simge adından önce dolar işareti ve ünlem işareti ($!) ekleyin. Sembol tanıma hakkında daha fazla bilgi için bkz. Sembol söz dizimi ve simge eşleştirme.
C++ ifadelerindeki yapılar
C++ ifade değerlendiricisi, sahte kaydedicileri uygun türlerine dönüştürür. Örneğin, $teb olarak TEB*yayınlanır.
0:000> ?? @$teb
struct _TEB * 0x004ec000
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : (null)
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : (null)
+0x02c ThreadLocalStoragePointer : 0x004ec02c Void
+0x030 ProcessEnvironmentBlock : 0x004e9000 _PEB
+0x034 LastErrorValue : 0xbb
+0x038 CountOfOwnedCriticalSections : 0
Aşağıdaki örnekte, başvurulan bir yapı üyesine işaretçi kullanımını gösteren TEB yapısındaki işlem kimliği gösterilir.
0:000> ?? @$teb->ClientId.UniqueProcess
void * 0x0000059c
C++ ifadelerindeki işleçler
Öncelik kurallarını geçersiz kılmak için parantez kullanabilirsiniz.
C++ ifadesinin bir bölümünü parantez içine alır ve ifadeden önce iki işareti (@@) eklerseniz, ifade MASM ifade kurallarına göre yorumlanır. İki @ işareti ile açılan parantez arasına boşluk ekleyemezsiniz. Bu ifadenin son değeri C++ ifade değerlendiricisine ULONG64 değer olarak geçirilir. İfade değerlendiricisini @@c++( ... ) veya @@masm( ... ) kullanarak da belirtebilirsiniz.
Veri türleri C++ dilinde her zamanki gibi gösterilir. Dizileri ([ ]), işaretçi üyelerini (->), UDT üyelerini (.) ve sınıfların üyelerini (::) gösteren simgelerin tümü tanınır. Atama ve yan etki işleçleri dahil olmak üzere tüm aritmetik işleçler desteklenir. Ancak, new, delete ve throw işleçlerini kullanamazsınız ve aslında bir işlevi çağıramazsınız.
İşaretçi aritmetiği desteklenir ve ofsetler doğru şekilde ölçeklendirilir. İşlev işaretçisine uzaklık ekleyemezsiniz. bir işlev işaretçisine uzaklık eklemeniz gerekiyorsa, önce uzaklığı bir karakter işaretçisine dönüştürebilirsiniz.
C++'da olduğu gibi, geçersiz veri türlerine sahip işleçler kullanırsanız söz dizimi hatası oluşur. Hata ayıklayıcının C++ ifade ayrıştırıcısı çoğu C++ derleyicisinden biraz daha gevşek kurallar kullanır, ancak tüm ana kurallar uygulanır. Örneğin, tamsayı olmayan bir değeri kaydıramazsınız.
Aşağıdaki işleçleri kullanabilirsiniz. Her hücredeki işleçler, alt hücrelerdeki işleçlere göre önceliklidir. Aynı hücredeki işleçler aynı önceliğe sahiptir ve soldan sağa ayrıştırılır.
C++ ile olduğu gibi ifade değerlendirmesi de değeri bilindiğinde sona erer. Bu son, gibi ?? myPtr && *myPtrifadeleri etkili bir şekilde kullanmanızı sağlar.
Referans ve tür dönüştürme
| Operatör | Anlamı |
|---|---|
| İfade // Yorum | Sonraki tüm metni yoksay |
| Sınıf :: Üye | Sınıfın üyesi |
| Sınıf ::~Üye | Sınıfın üyesi (yıkıcı) |
| :: Ad | Global |
| Yapısı . Alan | Bir yapıdaki alan |
| İşaretçi ->Alan | Başvurulan yapıdaki alan |
| Ad [tamsayı] | Dizi alt indis |
| LValue ++ | Artım (değerlendirmeden sonra) |
| LValue -- | Azaltma (değerlendirmeden sonra) |
| < dynamic_casttür>(Değer) | Typecast (her zaman gerçekleştirilir) |
| static_cast<tür>(Değer) | Typecast (her zaman gerçekleştirilir) |
| reinterpret_cast<tür>(Değer) | Typecast (her zaman gerçekleştirilir) |
| const_cast<tür>(Değer) | Typecast (her zaman gerçekleştirilir) |
Değer işlemleri
| Operatör | Anlamı |
|---|---|
| (tür) Değer | Typecast (her zaman gerçekleştirilir) |
| sizeofdeğeri | İfadenin boyutu |
| sizeof( tür ) | Veri türünün boyutu |
| ++ LValue | Artım (değerlendirmeden önce) |
| -- LValue | Azaltma (değerlendirmeden önce) |
| ~ Değer | Bit tamamlayıcısı |
| ! Değer | Değil (Boolean) |
| Değer | Tekli eksi |
| + Değer | Üniter artı |
| & LValue | Veri türünün adresi |
| Değer | Başvuru |
| Yapısı . İşaretçisi | Yapı üyesi işaretçisi |
| İşaretçi -> * İşaretçi | Referans verilen yapının üye işaretçisi |
Aritmetik
| Operatör | Anlamı |
|---|---|
| Değer Değeri | Çarpma |
| Değer / Değer | Bölüm |
| Değer % Değer | Modülü |
| Değer + Değer | İlave |
| Değer - Değer | Çıkarma |
| Değer<<Değer | Bit düzeyinde sola kaydırma |
| Değer>>Değer | Bit düzeyinde sağa kaydırma |
| Değer<Değer | "Daha az (karşılaştırma)" |
| Değer<= Değer | Küçük veya eşit (karşılaştırma) |
| Değer>Değer | Büyüktür (karşılaştırma) |
| Değer>= Değer | Büyüktür veya eşittir (karşılaştırma) |
| Değer == Değer | Eşittir (karşılaştırma) |
| Değer != Değer | Eşit değil (karşılaştırma) |
| Değer ve Değer | Bit Düzeyinde VE |
| Değer ^ Değer | Bit Düzeyinde XOR (özel OR) |
| Değer | Değer | Bit Düzeyinde OR |
| Mantıksal VE | |
| Değer || Değer | Mantıksal VEYA |
Aşağıdaki örneklerde sahte kayıtların gösterildiği gibi ayarlandığı varsayılır.
0:000> r $t0 = 0
0:000> r $t1 = 1
0:000> r $t2 = 2
0:000> ?? @$t1 + @$t2
unsigned int64 3
0:000> ?? @$t2/@$t1
unsigned int64 2
0:000> ?? @$t2|@$t1
unsigned int64 3
Görevlendirme
| Operatör | Anlamı |
|---|---|
| LValue = Değer | Atamak |
| LValue *= Değer | Çarpma ve atama |
| LValue /= Değer | Bölme ve atama |
| LValue %= Değer | Modulo ve atama |
| LValue += Değer | Ekleme ve atama |
| LValue -= Değer | Çıkarma ve atama |
| LValue<<= Değer | Sola kaydırma ve atama |
| LValue>>= Değer | Sağa kaydır ve ata |
| LValue &= Value | AND ve atama |
| LValue |= Değer | VEYA ve atama |
| LValue ^= Değer | XOR ile ata |
Değerlendirme
| Operatör | Anlamı |
|---|---|
| Değer mi? Değer : Değer | Koşullu değerlendirme |
| Değer , Değer | Tüm değerleri değerlendirin ve en sağdaki değer dışında tümünü at |
C++ ifadelerindeki makrolar
C++ ifadeleri içinde makroları kullanabilirsiniz. Makrolardan önce bir sayı işareti (#) eklemeniz gerekir.
Aşağıdaki makroları kullanabilirsiniz. Bu makrolar, aynı ada sahip Microsoft Windows makrolarıyla aynı tanımlara sahiptir. Windows makroları Winnt.h içinde tanımlıdır.
| Makro | Dönüş değeri |
|---|---|
| #CONTAINING_RECORD(Adres, Tür, Alan) | Yapının türü ve yapı içindeki bir alanın adresi göz önünde bulundurularak bir yapı örneğinin temel adresini döndürür. |
| #FIELD_OFFSET(Type, Field) | Bilinen bir yapı türündeki adlandırılmış alanın bayt uzaklığını döndürür. |
| #RTL_CONTAINS_FIELD(Yapı, Boyut, Alan) | Verilen bayt boyutunun istenen alanı içerip içermediğini gösterir. |
| #RTL_FIELD_SIZE(Tür, Alan) | Alanın türüne gerek kalmadan bilinen türde bir yapıdaki alanın boyutunu döndürür. |
| #RTL_NUMBER_OF(Dizi) | Statik olarak boyutlandırılmış bir dizideki öğelerin sayısını döndürür. |
| #RTL_SIZEOF_THROUGH_FIELD(Type, Field) | Belirtilen alanla birlikte bilinen türdeki bir yapının boyutunu döndürür. |
Bu örnek, yapıdaki #FIELD_OFFSET bir alana bayt uzaklığını hesaplamak için makronun kullanımını gösterir.
0:000> ?? #FIELD_OFFSET(_PEB, BeingDebugged)
long 0n2
Ayrıca bakınız
MASM ifadeleri ile C++ ifadeleri karşılaştırması
?? C++ ifadesini değerlendirme