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
[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
'-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
@hvd Gerçek bir örnek gönderdim. Bu sorunun GCC ile ilgili olup olmadığından emin değilim, bunu sadece Apple LLVM 8.0 –