Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menjelaskan penggunaan sintaks ekspresi C++ dengan alat penelusuran kesalahan Windows.
Debugger menerima dua jenis ekspresi numerik yang berbeda: ekspresi C++ dan ekspresi Microsoft Macro Assembler (MASM). Masing-masing ekspresi ini mengikuti aturan sintaksisnya sendiri untuk input dan output.
Untuk informasi selengkapnya tentang kapan setiap jenis sintaks digunakan, lihat Mengevaluasi ekspresi dan perintah ekspresi evaluasi ? .
Pengurai ekspresi C++ mendukung semua bentuk sintaks ekspresi C++. Sintaksnya mencakup semua jenis data, termasuk pointer, angka floating-point, dan array, dan semua operator unary dan biner C++.
Jendela Watch dan Locals di debugger selalu menggunakan evaluator ekspresi C++.
Dalam contoh berikut, perintah evaluate C++ expression menampilkan nilai register penunjuk instruksi.
0:000> ?? @eip
unsigned int 0x771e1a02
Kita dapat menggunakan fungsi C++ sizeof untuk menentukan ukuran struktur.
0:000> ?? (sizeof(_TEB))
unsigned int 0x1000
Atur evaluator ekspresi menjadi C++
Gunakan evaluator .expr choose expression untuk melihat evaluator ekspresi default dan mengubahnya menjadi C++.
0:000> .expr
Current expression evaluator: MASM - Microsoft Assembler expressions
0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions
Setelah evaluator ekspresi default diubah, perintah ekspresi evaluasi ? dapat digunakan untuk menampilkan ekspresi C++. Contoh berikut menampilkan nilai register pointer instruksi.
0:000> ? @eip
Evaluate expression: 1998461442 = 771e1a02
Untuk mempelajari selengkapnya tentang @eip register referensi, lihat Sintaks register.
Dalam contoh ini, nilai heks 0xD ditambahkan ke eip register.
0:000> ? @eip + 0xD
Evaluate expression: 1998461455 = 771e1a0f
Register dan pseudo-register dalam ekspresi C++
Anda dapat menggunakan register dan pseudo-register dalam ekspresi C++. Tanda @ harus ditambahkan sebelum register atau pseudo-register.
Evaluator ekspresi secara otomatis melakukan pemeran yang tepat. Register sesungguhnya dan pseudo-register nilai bilangan bulat diubah tipe ke ULONG64. Semua alamat dilemparkan ke PUCHAR, $thread dilemparkan ke ETHREAD*, $proc dilemparkan ke EPROCESS*, $teb dilemparkan ke TEB*, dan $peb dilemparkan ke PEB*.
Contoh ini menampilkan TEB.
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
Anda tidak dapat mengubah register atau pseudo-register dengan operator penugasan atau operator efek samping. Anda harus menggunakan perintah r registers untuk mengubah nilai-nilai ini.
Contoh berikut mengatur register pseudo ke nilai 5 lalu menampilkannya.
0:000> r $t0 = 5
0:000> ?? @$t0
unsigned int64 5
Untuk informasi selengkapnya tentang register dan pseudo-register, lihat Sintaks register dan Sintaks pseudo-register.
Angka dalam ekspresi C++
Angka dalam ekspresi C++ ditafsirkan sebagai angka desimal, kecuali Anda menentukannya dengan cara lain. Untuk menentukan bilangan bulat heksadesimal, tambahkan 0x sebelum angka. Untuk menentukan bilangan bulat oktal, tambahkan 0 (nol) sebelum angka.
Radix debugger default tidak memengaruhi cara Anda memasukkan ekspresi C++. Anda tidak dapat langsung memasukkan angka biner, kecuali dengan menumpuk ekspresi MASM dalam ekspresi C++.
Anda dapat memasukkan nilai heksadesimal 64-bit dalam format xxxxxxxx'xxxxxxxx. Anda juga dapat menghilangkan aksen kuburan ('). Kedua format menghasilkan nilai yang sama.
Anda dapat menggunakan akhiran L, U, dan I64 dengan nilai bilangan bulat. Ukuran aktual angka yang dibuat tergantung pada akhiran dan angka yang Anda masukkan. Untuk informasi selengkapnya tentang interpretasi ini, lihat referensi bahasa C++.
Output evaluator ekspresi C++ mempertahankan jenis data yang ditentukan aturan ekspresi C++. Namun, jika Anda menggunakan ekspresi ini sebagai argumen untuk perintah, casting selalu dilakukan. Misalnya, Anda tidak perlu melemparkan nilai bilangan bulat ke penunjuk saat digunakan sebagai alamat dalam argumen perintah. Jika nilai ekspresi tidak dapat ditransmisikan secara valid ke bilangan bulat atau penunjuk, kesalahan sintaks terjadi.
Anda dapat menggunakan awalan 0n (desimal) untuk beberapa output, tetapi Anda tidak dapat menggunakannya untuk input ekspresi C++.
Karakter dan string dalam ekspresi C++
Anda dapat memasukkan karakter dengan mengelilinginya dengan tanda kutip tunggal ('). Karakter escape C++ standar diizinkan.
Anda dapat memasukkan literal string dengan mengelilinginya dengan tanda kutip ganda ("). Anda dapat menggunakan \" sebagai urutan escape dalam string seperti itu. Namun, string tidak memiliki arti untuk evaluator ekspresi.
Simbol dalam ekspresi C++
Dalam ekspresi C++, setiap simbol ditafsirkan sesuai dengan jenisnya. Bergantung pada apa yang dirujuk oleh simbol, simbol tersebut mungkin ditafsirkan sebagai bilangan bulat, struktur data, penunjuk fungsi, atau jenis data lainnya. Kesalahan sintaks terjadi jika Anda menggunakan simbol yang tidak sesuai dengan jenis data C++, seperti nama modul yang tidak dimodifikasi, dalam ekspresi C++.
Anda dapat menggunakan aksen kuburan (') atau apostrof (') dalam nama simbol hanya jika Anda menambahkan nama modul dan tanda seru sebelum nama simbol. Saat Anda menambahkan pemisah < dan > setelah nama templat, Anda dapat menambahkan spasi di antara pemisah ini.
Jika simbol mungkin ambigu, Anda dapat menambahkan nama modul dan tanda seru (!) atau hanya tanda seru sebelum simbol. Untuk menentukan bahwa simbol dimaksudkan sebagai lokal, hilangkan nama modul, dan sertakan tanda dolar dan tanda seru ($!) sebelum nama simbol. Untuk informasi selengkapnya tentang pengenalan simbol, lihat Sintaks simbol dan pencocokan simbol.
Struktur dalam ekspresi C++
Evaluator ekspresi C++ mengonversi pseudo-registers ke tipe yang sesuai. Misalnya, $teb diubah sebagai TEB*.
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
Contoh berikut menampilkan ID proses dalam struktur TEB yang memperlihatkan penggunaan penunjuk kepada anggota struktur yang dirujuk.
0:000> ?? @$teb->ClientId.UniqueProcess
void * 0x0000059c
Operator dalam ekspresi C++
Anda dapat menggunakan tanda kurung untuk mengambil alih aturan prioritas.
Jika Anda menyertakan bagian dari ekspresi C++ dalam tanda kurung dan menambahkan dua tanda at (@@) sebelum ekspresi, ekspresi ditafsirkan sesuai dengan aturan ekspresi MASM. Anda tidak dapat menambahkan spasi antara dua tanda at dan tanda kurung buka. Nilai akhir ekspresi ini diteruskan ke evaluator ekspresi C++ sebagai nilai ULONG64. Anda juga dapat menentukan evaluator ekspresi dengan menggunakan @@c++( ... ) atau @@masm( ... ).
Jenis data ditunjukkan seperti biasa dalam bahasa C++. Simbol yang menunjukkan array ([ ]), anggota penunjuk (->), anggota UDT (.), dan anggota kelas (::) semuanya dikenali. Semua operator aritmatika didukung, termasuk operator penugasan dan operator efek samping. Namun, Anda tidak dapat menggunakan newoperator , delete, dan throw , dan Anda tidak dapat benar-benar memanggil fungsi.
Aritmatika penunjuk didukung dan offset diskalakan dengan benar. Perhatikan bahwa Anda tidak dapat menambahkan offset ke penunjuk fungsi. Jika Anda harus menambahkan offset ke penunjuk fungsi, transmisikan offset ke penunjuk karakter terlebih dahulu.
Seperti di C++, jika Anda menggunakan operator dengan jenis data yang tidak valid, kesalahan sintaks terjadi. Pengurai ekspresi C++ debugger menggunakan aturan yang sedikit lebih longgar daripada sebagian besar kompilator C++, tetapi semua aturan utama tetap diberlakukan. Misalnya, Anda tidak dapat menggeser nilai non-bilangan bulat.
Anda dapat menggunakan operator berikut. Operator di setiap sel lebih diutamakan daripada operator dalam sel yang lebih rendah. Operator dalam sel yang sama memiliki prioritas yang sama dan diurai dari kiri ke kanan.
Seperti halnya C++, evaluasi ekspresi berakhir ketika nilainya diketahui. Akhiran ini memungkinkan Anda menggunakan ekspresi secara efektif seperti ?? myPtr && *myPtr.
Referensi dan konversi tipe
| Pengoperasi | Makna |
|---|---|
| Ekspresi // Komentar | Abaikan semua teks berikutnya |
| Kelas :: Anggota | Anggota kelas |
| Kelas ::~Anggota | Anggota kelas (destruktor) |
| :: Nama | Mendunia |
| Struktur . Ladang | Bidang dalam struktur |
| Pointer ->Field | Bidang dalam struktur yang dirujuk |
| Nama [bilangan bulat] | Indeks array |
| LValue ++ | Kenaikan (setelah evaluasi) |
| LValue -- | Pengurangan (setelah evaluasi) |
| < dynamic_castjenis>(Nilai) | Typecast (selalu dilakukan) |
| < static_castjenis>(Nilai) | Typecast (selalu dilakukan) |
| < reinterpret_castjenis>(Nilai) | Typecast (selalu dilakukan) |
| const_cast<type>(Value) | Typecast (selalu dilakukan) |
Operasi nilai
| Pengoperasi | Makna |
|---|---|
| (jenis) Nilai | Typecast (selalu dilakukan) |
| sizeof nilaivalue | Ukuran ekspresi |
| sizeof( type ) | Ukuran tipe data |
| ++ LValue | Kenaikan (sebelum evaluasi) |
| -- LValue | Pengurangan (sebelum evaluasi) |
| ~ Nilai | Pelengkap bit |
| ! Nilai | Bukan (Boolean) |
| Nilai | Minus tidak sah |
| + Nilai | Nilai tambah unary |
| & LValue | Alamat tipe data |
| Nilai | Mengakses nilai penunjuk |
| Struktur . Pointer | Penunjuk ke anggota struktur |
| Penunjuk -> * Penunjuk | Penunjuk ke anggota struktur yang dirujuk |
Aritmetika
| Pengoperasi | Makna |
|---|---|
| Nilai Nilai | Perkalian |
| Nilai / Nilai | Divisi |
| Nilai % Nilai | Modulus |
| Nilai + Nilai | Penambahan |
| Nilai - Nilai | Pengurangan |
| Nilai<<Nilai | Pergeseran bit ke kiri |
| Nilai>>Nilai | Pergeseran bit ke kanan |
| Nilai<Nilai | Kurang dari (perbandingan) |
| Nilai<= Nilai | Kurang dari atau sama dengan (perbandingan) |
| Nilai>Nilai | Lebih besar dari (perbandingan) |
| Nilai>= Nilai | Lebih besar dari atau sama dengan (perbandingan) |
| Nilai == Nilai | Sama dengan (untuk perbandingan) |
| Nilai != Nilai | Tidak sama (perbandingan) |
| Nilai dan Nilai | Bitwise DAN |
| Nilai ^ Nilai | Bitwise XOR (eksklusif OR) |
| Nilai | Nilai | Bitwise ATAU |
| DAN Logika | |
| Nilai || Nilai | ATAU Logika |
Contoh berikut mengasumsikan bahwa register pseudo diatur seperti yang ditunjukkan.
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
Penugasan
| Pengoperasi | Makna |
|---|---|
| LValue = Nilai | Menetapkan |
| LValue *= Nilai | Mengalikan dan menetapkan |
| LValue /= Nilai | Membagi dan menetapkan |
| LValue %= Nilai | Modulo dan tetapkan |
| LValue += Nilai | Menambahkan dan mengalokasikan |
| LValue -= Nilai | Mengurangi dan menetapkan |
| LValue<<= Nilai | Geser ke kiri dan alihkan |
| LValue>>= Nilai | Geser ke kanan dan berikan nilai |
| LValue&=Value | DAN dan tetapkan |
| LValue |= Nilai | ATAU dan tetapkan |
| LValue ^= Nilai | XOR dan tetapkan nilai |
Evaluasi
| Pengoperasi | Makna |
|---|---|
| Nilai ? Nilai : Nilai | Evaluasi bersyarat |
| Nilai , Nilai | Evaluasi semua nilai, lalu buang semua kecuali nilai paling kanan |
Makro dalam ekspresi C++
Anda dapat menggunakan makro dalam ekspresi C++. Anda harus menambahkan tanda angka (#) sebelum makro.
Anda bisa menggunakan makro berikut. Makro ini memiliki definisi yang sama dengan makro Microsoft Windows dengan nama yang sama. Makro Windows didefinisikan dalam Winnt.h.
| Makro | Mengembalikan nilai |
|---|---|
| #CONTAINING_RECORD(Alamat, Jenis, Bidang) | Mengembalikan alamat dasar instans struktur, mengingat jenis struktur dan alamat bidang dalam struktur. |
| #FIELD_OFFSET(Jenis, Bidang) | Mengembalikan offset byte dari bidang bernama dalam jenis struktur yang diketahui. |
| #RTL_CONTAINS_FIELD(Struct, Size, Field) | Menunjukkan apakah ukuran byte yang diberikan menyertakan bidang yang diinginkan. |
| #RTL_FIELD_SIZE(Jenis, Bidang) | Mengembalikan ukuran bidang dalam struktur jenis yang diketahui, tanpa memerlukan jenis bidang. |
| #RTL_NUMBER_OF(Array) | Mengembalikan jumlah elemen dalam array berukuran statis. |
| #RTL_SIZEOF_THROUGH_FIELD(Type, Field) | Mengembalikan ukuran sebuah struktur dari jenis yang diketahui, termasuk hingga ke bidang yang ditentukan. |
Contoh ini memperlihatkan penggunaan Makro #FIELD_OFFSET untuk menghitung offset byte suatu bidang dalam struktur.
0:000> ?? #FIELD_OFFSET(_PEB, BeingDebugged)
long 0n2
Lihat juga
Ekspresi MASM vs. ekspresi C++
? mengevaluasi ekspresi (matematika/logika)