Bu dokümanda, AGDE kullanılırken özel hata ayıklama araçlarının nasıl etkinleştirileceği gösterilmektedir. Bu araçlar, teşhisi zor olan bellek bozulması ve üzerine yazma hatalarında yardımcı olabilir.
HWAddress Sanitizer ve Address Sanitizer
HWAddress Sanitizer (HWASan) ve Address Sanitizer (ASan), bellek bozulması ve aşağıdaki gibi hataların üzerine yazma hatalarını ayıklamaya yardımcı olan bellek bozulması ayıklama araçlarıdır:
- Yığın tamponu taşmaları ve eksik dolgular
- Yığın tamponu taşmaları ve eksik dolgular
- Stack'in kapsamı dışında kullanılması
- İkili boşluk ve vahşi boşluk hataları
- Döndürme işleminden sonra yığın kullanımı (yalnızca HWASan)
HWASan veya ASan'ı yalnızca bir sorunla ilgili hata ayıklama işlemi yaparken veya otomatik testin bir parçası olarak etkinleştirmenizi öneririz. Bu araçlar performans açısından iyi olsa da bunların kullanımı cezaya neden olur.
Çalışma zamanı davranışı
Etkinleştirildiğinde hem HWASan hem de ASan, uygulamanızdaki bellek bozulmasını otomatik olarak kontrol eder.
Bir bellek hatası algılanırsa uygulama SIGBART
(sinyal iptal) hatasıyla kilitlenir ve logcat'e ayrıntılı bir mesaj yazdırır. İletinin bir kopyası da /data/tombstones
altındaki bir dosyaya yazılır.
Hata mesajı aşağıdaki gibi görünür:
ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
#0 0x7b24d90a08 (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
#1 0x7b8f1e4ccc (/apex/com.android.art/lib64/libart.so+0x198ccc)
#2 0x7b8f1db364 (/apex/com.android.art/lib64/libart.so+0x18f364)
#3 0x7b8f2ad8d4 (/apex/com.android.art/lib64/libart.so+0x2618d4)
0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
#0 0x7b92a322bc (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
#1 0x7b24d909e0 (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
#2 0x7b8f1e4ccc (/apex/com.android.art/lib64/libart.so+0x198ccc)
Ön koşullar
HWASan gereksinimleri
HWASan'ı kullanmak için:
- AGDE 24.1.99 veya daha yeni bir sürümü kullanmanız gerekir.
- Uygulama, NDK 26 veya daha yeni bir sürüm kullanılarak derlenmiş olmalıdır.
- Uygulama, hedef SDK 34 veya sonraki bir sürümle derlenmiş olmalıdır.
- Hedef, Android 14 (API düzeyi 34) veya sonraki sürümleri çalıştıran bir
arm64-v8a
cihaz olmalıdır.
Projenizde paylaşılan C++ Standart Kitaplığı'nı kullanma
Bilinen bir sorun nedeniyle ASan, libc++_static
kullanıldığında C++ istisna işlemeyle uyumlu değildir. Bu sorun, libc++_shared
kullanılırken görülmez.
HWASan, new
ve delete
operatörlerinin kendi uygulamasını kullanır. Standart kitaplık projeye statik olarak bağlanırsa bu operatörler kullanılamaz.
Bu ayarı değiştirmek için bu dokümanın C++ Standart Kitaplığı'nı bağlama bölümüne bakın.
Çerçeve İşaretçisi oluşturmayı etkinleştir
HWASan ve ASan, bellek ayırma ve bellek ayırma etkinlikleri için yığın izleme bilgilerini oluşturmak üzere hızlı çerçeve işaretçisine dayalı bir çözücü kullanır. Bu, bu özellikleri kullanmak için C++ derleyici ayarlarınızda çerçeve işaretçisi oluşturmayı etkinleştirmeniz gerektiği anlamına gelir. Yani kare işaretçisi atlama optimizasyonunu devre dışı bırakmanız gerekir.
Bu ayarı değiştirmek için bu dokümanın Çerçeve İşaretçisi Oluşturma özelliğini etkinleştirme bölümüne bakın.
Visual Studio projenizi HWASan veya ASan kullanacak şekilde yapılandırma
HWASan veya ASan'ı etkinleştirme
HWASan veya ASan'ı etkinleştirmek için projenizin Mülk Sayfaları'nda Yapılandırma Özellikleri > Genel'e gidin.
Şekil 1: Visual Studio Çözüm Gezgini penceresindeki projenin Özellikler seçeneği.
Şekil 2: Genel proje özelliklerindeki Address Sanitizer (ASan) ayarı.
Projeniz için HWASan'ı etkinleştirmek üzere Address Sanitizer (ASan) ayarını Hardware ASan Enabled (fsanitize=hwaddress) olarak değiştirin.
Projeniz için ASan'ı etkinleştirmek üzere Address Sanitizer (ASan) ayarını ASan Enabled (fsanitize=address) olarak değiştirin.
Çerçeve işaretçisi oluşturmayı etkinleştirme
Çerçeve İşaretçisi oluşturma, Çerçeve İşaretçisini Atla C/C++ derleyici ayarı tarafından kontrol edilir ve projenizdeki Yapılandırma Özellikleri > C/C++ > Optimizasyon altındaki Mülk Sayfaları'nda bulunabilir.
Şekil 3: Çerçeve İşaretçisini Atla ayarının bulunduğu yer.
HWASan veya ASan kullanırken Çerçeve İşaretçisini Atla ayarını Hayır (-fno-omit-frame-pointer) olarak ayarlayın.
C++ Standart Kitaplığı'nı paylaşılan kitaplık modunda bağlama
C++ Standart Kitaplığı için bağlayıcı modu ayarını, projenizin Özellik Sayfaları'ndaki Yapılandırma Özellikleri > Genel bölümündeki Proje Varsayanları bölümünde bulabilirsiniz.
Şekil 4: C++ Standart Kitaplığı için bağlayıcı modu ayarının bulunduğu yer.
HWASan veya ASan kullanırken STL kullanımı'nı C++ Standart Kitaplıklarını (.so) kullan olarak ayarlayın. Bu değer, C++ standart kitaplığını paylaşılan kitaplık olarak projenize bağlar. Bu, HWASan ve ASan'ın düzgün çalışması için gereklidir.
Address Sanitizer kullanımı için derleme yapılandırması oluşturma
HWASan veya ASan'ı geçici olarak kullanmayı tercih ediyorsanız yalnızca bu ikisini kullanmak için yeni bir derleme yapılandırması oluşturmak istemeyebilirsiniz. Projeniz küçükse, özelliği keşfediyorsanız veya test sırasında keşfettiğiniz bir soruna yanıt olarak bu durumla karşılaşabilirsiniz.
Ancak bu özelliği faydalı bulup düzenli olarak kullanmayı planlıyorsanız Çaydanlık örneğinde gösterildiği gibi HWASan veya ASan için yeni bir derleme yapılandırması oluşturabilirsiniz. Örneğin, birim testlerinizin bir parçası olarak veya oyununuzun gece boyunca yapılan ilk testleri sırasında Address Sanitizer'ı düzenli olarak çalıştırırsanız bunu yapabilirsiniz.
Ayrı bir derleme yapılandırması oluşturmak, özellikle çok sayıda farklı üçüncü taraf kitaplığı kullanan ve bu kitaplıkları normalde C++ standart kitaplığına statik olarak bağladığınız büyük bir projeniz varsa yararlı olabilir. Özel derleme yapılandırmaları, proje ayarlarınızın her zaman doğru kalmasını sağlamanıza yardımcı olabilir.
Derleme yapılandırması oluşturmak için projenizin Mülk Sayfaları'nda Yapılandırma Yöneticisi… düğmesini tıklayın ve ardından Etkin çözüm yapılandırması açılır menüsünü açın. Ardından
HWASan'ı özel bellek ayırıcılarla kullanma
HWASan, işaretçilere etiket ekleyebilmesi ve etiket uyuşmazlıklarını kontrol edebilmesi için malloc
(veya new
) aracılığıyla ayrılan belleği otomatik olarak keser.
Ancak özel bellek ayırıcı kullanıldığında HWASan, özel bellek ayırma yöntemlerinize otomatik olarak müdahale edemez. Bu nedenle, HWASan'ı özel bellek ayırıcınızla kullanmak istiyorsanız bellek ayırıcınızı HWASan'ı açıkça çağıracak şekilde donatın. Bu işlem yalnızca birkaç satır kodla yapılabilir.
Ön koşullar
Çağırmanız gereken HWASan yöntemleri bu başlıkta tanımlanmıştır:
#include "sanitizer/hwasan_interface.h"
Bellek ayırma yönteminizin performansını ölçme
Nesneleri 16 baytlık blok ayrıntı düzeyinde ve hizalamayla ayırın. Örneğin, 24 bayt boyutunda sabit boyutlu nesneler sunan bir havuz ayırıcınız varsa ayırma işlemlerinizi 32 bayta yuvarlayın ve 16 bayta hizalayın.
8 bitlik bir etiket oluşturun. Bu değerler dahili kullanım için ayrıldığından etiketinizde 0-16 değerleri kullanılmamalıdır.
HWASan'ı etkinleştirerek bellek bölgesini bu etiketle izlemeye başlayın:
__hwasan_tag_memory((void*) address, tag, size);
Etiketi işaretçinizin üst 8 bitine ekleyin:
address = __hwasan_tag_pointer((void*) address, tag);
Bellek ayırma yönteminizi ayarlama
Mevcut etiketli işaretçiler aracılığıyla daha fazla erişimin başarısız olmasına neden olmak için bellek bölgesi etiketini sıfırlayın:
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
Önceden ayrılmış bir nesne havuzuyla çalışma
Bellek ayırıcınız, nesneleri bir havuzda önceden ayırır ve gerçekten serbest bırakmak yerine havuza geri döndürüyorsa bellek ayırma yönteminiz, bellek ve işaretçi etiketinin doğrudan üzerine yeni bir değer yazabilir:
```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```
Bu tekniği kullanırsanız ayırma yöntemlerinizin işaretçileri veya bellek bloklarını etiketlemesi gerekmez. Bunun yerine, işaretçileri ve bellek bloklarını havuzunuzdaki nesneleri önceden ayırırken etiketlemeniz gerekir. Bu stilin kullanıldığı bir örnek için PoolAllocator örneğine bakın.