2016-12-02 35 views
8

Dereferenced işaretçiyi işaretçisine göstererek NULL işaretçisiyle büyük çekler kullanan çok eski (ve büyük) Win32 projesine sahibim. Şunun gibi:NULL işaretçisini geçersiz kılmaya izin ver

int* x = NULL; //somewhere 
//... code 
if (NULL == &(*(int*)x) //somewhere else 
    return; 

Ve evet, bu kod aptal olduğunu biliyoruz ve refactored gerekiyor. Ancak büyük miktarda kod nedeniyle imkansız. Şu anda Xcode'ta MacOS Sierra'nın altında bu projeyi derlemem gerekiyor, bu da büyük sorunlara yol açıyor ... Bu durum, çıkış modunda (kod optimizasyonu ile) durumun yanlış davranışla yürütüldüğünü gösteriyor (NULL öğesinin kaldırılması nedeniyle tanımlanmamış davranışlar deniyor) Işaretçi).

this document for GCC göre bir seçenek -fno-silme-boş-işaretçi-çekler yoktur, ancak O1, O2 veya O3 optimizasyonu etkin zaman LLVM için çalışmıyor görünüyor. Yani soru şu: LLVM 8.0 derleyicisini bu gibi referanslara izin vermek için nasıl zorlayabilirim?

GÜNCELLEME. Sorunu kontrol etmek için gerçek çalışma örneği.

//somewhere 1 
class carr 
{ 
public: 
    carr(int length) 
    { 
     xarr = new void*[length]; 

     for (int i = 0; i < length; i++) 
      xarr[i] = NULL; 
    } 

    //some other fields and methods 

    void** xarr; 
    int& operator[](int i) 
    { 
     return *(int*)xarr[i]; 
    } 
}; 

//somewhere 2 
carr m(5); 

bool something(int i) 
{ 
    int* el = &m[i]; 
    if (el == NULL) 
     return FALSE; //executes in debug mode (no optimization) 

    //other code 
    return TRUE; //executes in release mode (optimization enabled) 
} 
-O0 ve -O1, something keeps the null check anda

ve kod "çalıştığını":

something(int):       # @something(int) 
    pushq %rax 
    movl %edi, %eax 
    movl $m, %edi 
    movl %eax, %esi 
    callq carr::operator[](int) 
    movb $1, %al 
    popq %rcx 
    retq 

Ama -O2 de ve üzeri, the check is optimized out:

something(int):       # @something(int) 
    movb $1, %al 
    retq 
+5

[Karşılık gelen hata raporu] (https://llvm.org/bugs/show_bug.cgi?id=9251). Bu umut verici değil: bayrak gerçekten şimdilik göz ardı ediliyor (önce tanınmadı). – Quentin

+1

'-fno-delete-null-pointer-checks'' & * (int *) x' etkilememesi gerekiyordu, hala 'NULL' olmasına izin verilmesi gerekiyordu. Http://gcc.godbolt.org/ üzerinde clang ile kontrol etmek, basitçe bool b (kısa * p) {return 0 == & * (int *) p; } ', clang doğru kodu üretir. Lütfen derleyicinizin yanlış kod oluşturduğu minimal bir tam program gönderin. – hvd

+0

@hvd Gerçek bir örnek gönderdim. Bu sorunun GCC ile ilgili olup olmadığından emin değilim, bunu sadece Apple LLVM 8.0 –

cevap

0

bir metin tabanlı arama yapın BOŞ. Ardından, derleyici uyarı modunda çalıştırın ve kağıt üzerindeki tüm uyarıları yazdırın (eğer hala böyle bir teknolojiniz varsa). Her null için, sorunlu bir boş mu yoksa iyi mi? Sorunluysa, XNULL olarak yeniden adlandırın.

Şimdi C++ denetimleri, 640k kurulu olduğu için küçük bir sistemde başarısız olabilir, çünkü 640k herkes için yeterli, ancak modern sisteminizde pek çok GB bulunmuyor. Bu yüzden onları yeniden etiketledikten sonra çıkar. Eğer durum böyle değilse. XNULL'u C++ gözlerinde geçerli bir adrese sahip bir "kukla nesne" yapın.

(Örneğinden, kod bir Lisp yorumlayıcısına benziyor. Lisp'in hem boş göstericiye hem de kukla işaretçisine ihtiyacı var, tercümanın başka kolay bir yolu yok).

+0

Bu çözüm değil –