Programdaki varsayımları doğrulamak

taydin

Timur Aydın
Staff member
Katılım
24 Şubat 2018
Mesajlar
21,862
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.

C:
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?

C:
#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:

C:
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
5,880
Mesajlar
100,216
Üyeler
2,490
Son üye
ozavn

Son kaynaklar

Son profil mesajları

gruptaki arkadaşlara selamlar. sıteyi bu gün fark ettim. Asansör için 2x7 segment LCD gösterge üretmek istiyorum. acaba bu sayfadaki arkadaşlardan destek alabilirmiyim. LCD nin mantık açılımı ektedir.
deneyci wrote on TA3UIS's profile.
Selam.
Amatör telsiz lisansı nasıl alınıyor?
Lisansı olmayanı forumlarına almıyorlar. :)
Bilgi alamıyoruz.
cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Back
Top