Programdaki varsayımları doğrulamak

taydin

Timur Aydın
Staff member
Katılım
24 Şubat 2018
Mesajlar
25,190
Aşağıdaki örnek koddan gidelim. Burada bir EVENT yapısı tanımlı. 20 bytelık da bir "data" array var. Bu data array içerisine de EVENT_BUTTON veya daha farklı bir yapıyı yerleştireceğiz. Burada hemen bir risk ortaya çıkıyor. Eğer EVENT_BUTTON yapısına fazla eleman eklersek ve yapının boyutu 20 byte'ı geçerse, derleyici bize en ufak bir uyarı dahi vermeyecek ve programı başarılı bir şekilde derleyecek. Ama sonra programı çalıştırınca bellekte birşeyleri bozacağız. Ya program tamamen çökecek, veya kestirilemez şekilde yanlış çalışacak.

Kod:
enum EVENT_TYPES
{
    ET_BUTTON,
    ET_ENCODER,
    ET_NETWORK,
    ET_TIMER,
};

typedef struct
{
    enum EVENT_TYPES type;
    unsigned char data[20];

} EVENT;

typedef struct
{
    enum BUTTON_TYPES type;
    unsigned int id;
    enum BUTTON_ACTIONS action;
    unsigned int duration;

} EVENT_BUTTON;

#define event_button_init(event, _type, _id, _action, _duration)    \
    EVENT event;                                                    \
    {                                                               \
        event.type = ET_BUTTON;                                     \
        EVENT_BUTTON* p = (EVENT_BUTTON*)event.data;                \
        p->type = _type;                                            \
        p->id = _id;                                                \
        p->action = _action;                                        \
        p->duration = _duration;                                    \
    }
 
Bunu nasıl engelleyebiliriz? C/C++ preprocessor'u kullanarak şöyle bir trick atsak?

Kod:
#if (sizeof(EVENT_BUTTON) > sizeof(((EVENT*)0)->data))
    #error "EVENT_BUTTON fazla buyuk"
#endif

Ama bunu yapınca da GCC ön işleyici (preprocessor) doğrudan hata veriyor. Hatanın sebebi, ön işleme aşamasında daha yapıların net boyutları belli değil, o yüzden sizeof operatörü kullanılamıyor.
 
Ama mevcut C/C++ standartları arasında c11 veya sonrasını seçersek, orada tam da bu problemin çözümü için bir destek eklenmiş. Şu anda benim kullandığım standart c99 idi (1999 standardı). c11 ise 2011 yılında ortaya konan standart. C/C++ yerinde durmuyor, c11 den sonra da çok sayıda yeni standart çıktı, ama mevcut üzerinde çalıştığım kütüphanelerin derlenebileceğinin veya bir sorun çıkmayacağının bir garantisi yok. O yüzden benim istediğim özelliği sağlayan EN ESKİ standart olan c11 tercih ettim. Bu standartta, _Static_assert denen bir derleme zamanı operatörü geliyor. Bu operatörün, çok eskiden beri C/C++ da var olan assert ten farkı, herhangi bir kod üretmemesi ve sadece derleme aşamasında program üzerinde bazı varsayımları kontrol etmeye yaraması.

Kullanalım:

Kod:
typedef struct
{
    enum BUTTON_TYPES type;
    unsigned int id;
    enum BUTTON_ACTIONS action;
    unsigned int duration;

} EVENT_BUTTON;

_Static_assert(sizeof(EVENT_BUTTON) <= sizeof(((EVENT*)0)->data), "structure too large");

#define event_button_init(event, _type, _id, _action, _duration)    \
    EVENT event;                                                    \
    {                                                               \
        event.type = ET_BUTTON;                                     \
        EVENT_BUTTON* p = (EVENT_BUTTON*)event.data;                \
        p->type = _type;                                            \
        p->id = _id;                                                \
        p->action = _action;                                        \
        p->duration = _duration;                                    \
    }

Bu şekilde kullanınca, artık EVENT_BUTTON yapısının toplam büyüklüğü ile EVENT yapısındaki "data" array inin büyüklüğünü karşılaştırıyor. Eğer EVENT_BUTTON a fazla ilaveler yapılmışsa, programda hemen derleme hatası meydana geliyor. C/C++ kodunun daha güvenli ve hacklemeye dayanıklı hale getirmek için bu tip derleyici özelliklerini kesinlikle öğrenip kullanmak lazım. C/C++ derleyicisi, bu tip hatalar konusunda çok liberaldir, hiçbir sorun çıkarmadan derler. Sen de bu hatayı yaptığını çok daha sonra, ürün piyasaya çıkıp şikayetler gelmeye başlayınca anlarsın :)
 
bahsettigin durumun aynisi gomulu sisteme kod yazarken basima gelmisti, kod ilk basta dogru calisirken data akisi devam ettikce veriler bozulmaya basliyordu, en basit lcd ekrana yazilan datalar bile bozuk basiliyordu, ben sorunu temel yapida ararken, asil sorun tanimladigim dizi de tasma meydana gelmesiymis, tabi bunu bulmak gunlerimi almisti, o zaman buldugum cozum data boyutlarini ve veri tiplerini cok kati kurallara baglamakti, guzel bilgi tesekkurler.
 

Forum istatistikleri

Konular
7,718
Mesajlar
128,457
Üyeler
3,117
Son üye
MekanikAdam

Son kaynaklar

Son profil mesajları

Python Geliştirmeye eklediğim yapay zeka sunucusu, yeni başlayanlar için roket etkisi
Bir insanın zeka seviyesinin en kolay tesbiti, sorduğu sorulardır.
yapay zeka interneti yedi bitirdi, arama motoru kullanan, forumlara yazan kaldı mı ?
Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
az bilgili çok meraklı
Back
Top