C Academy · Ders

Tür Güvenliği Kaygıları

Değişken bağımsız değişkenlerin riskleri

3. ders / 413 adım

Tür Güvenliği Kaygıları, CoddyKit'te ücretsiz bir C Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C Academy kursu toplamda 4 dersten oluşur.

Değişken sayıda bağımsız değişken tür denetimini atlar

Normal C işlevleri, bağımsız değişkenlerin parametre türleriyle eşleşip eşleşmediğini denetler. Değişken sayıda bağımsız değişken bu denetimi tamamen atlar.

Derleyici, ... sonrasında ne geçirdiğinizi doğrulayamaz; bu da hataları kolayca yapılır ve tehlikeli hâle getirir.

#include <stdio.h>
#include <stdarg.h>

int add(int n, ...) {
    va_list a; va_start(a, n);
    int s = 0;
    for (int i = 0; i < n; i++) s += va_arg(a, int);
    va_end(a);
    return s;
}

int main(void) {
    printf("%d\n", add(2, 3, 4));
    return 0;
}

va_arg içinde yanlış tür

Bir bağımsız değişkeni yanlış türle okursanız sonuç tanımsız davranış olur.

Bir int geçirip bunu double olarak okumak, ilgisiz baytları yeniden yorumlar ve anlamsız bir değer veya çökme üretir.

#include <stdio.h>
#include <stdarg.h>

int read_int(int n, ...) {
    va_list a; va_start(a, n);
    int v = va_arg(a, int);
    va_end(a);
    return v;
}

int main(void) {
    printf("%d\n", read_int(1, 100));
    return 0;
}

Biçim dizisi uyumsuzlukları

printf tarzı işlevlerde yanlış belirteç, klasik bir hatadır. printf("%d", 3.14), bir double değeri int değer gibi okur.

Modern derleyiciler sabit değerlerdeki uyumsuzluklar konusunda uyarır; ancak çalışma zamanında oluşturulan biçim dizilerini yakalayamaz.

#include <stdio.h>

int main(void) {
    double pi = 3.14;
    printf("%f\n", pi);
    return 0;
}

Tam sayı yükseltmelerinin şaşırtıcı sonuçları

Küçük türler, değişken sayıda bağımsız değişken bölümünde int türüne yükseltilir. Bu nedenle bir char geçirseniz bile onu int olarak geri okumalısınız.

va_arg(a, char) ile char olarak okumak tanımsızdır.

#include <stdio.h>
#include <stdarg.h>

void show(int n, ...) {
    va_list a; va_start(a, n);
    int c = va_arg(a, int);
    printf("char is %c\n", c);
    va_end(a);
}

int main(void) {
    show(1, 'A');
    return 0;
}

Float türü double olur

Bir float bağımsız değişkeni, değişken sayıda bağımsız değişkenlerde her zaman double türüne yükseltilir. Onu double olarak okumalı, hiçbir zaman float olarak okumamalısınız.

Bu, değişken sayıda bağımsız değişkenlerle ilgili en yaygın hatalardan biridir.

#include <stdio.h>
#include <stdarg.h>

void show(int n, ...) {
    va_list a; va_start(a, n);
    double d = va_arg(a, double);
    printf("%.2f\n", d);
    va_end(a);
}

int main(void) {
    float f = 1.5f;
    show(1, f);
    return 0;
}

Gereğinden fazla bağımsız değişken okumak

Kodunuz, çağıranın sağladığından daha fazla kez va_arg çağırırsa yığından anlamsız veriler okursunuz.

Doğru bir sayı veya sentinel kullanmak bu nedenle zorunludur.

#include <stdio.h>
#include <stdarg.h>

int sum(int n, ...) {
    va_list a; va_start(a, n);
    int s = 0;
    for (int i = 0; i < n; i++) s += va_arg(a, int);
    va_end(a);
    return s;
}

int main(void) {
    printf("%d\n", sum(3, 1, 2, 3));
    return 0;
}

NULL işaretçisi sentinel'ları dikkat gerektirir

Sentinel olarak NULL kullanmak risklidir: bazı platformlarda NULL, işaretçiden farklı boyuta sahip bir int olan 0 değeridir.

Doğru türün geçirildiğinden emin olmak için (char *)NULL gibi açıkça tür dönüşümü uygulayın.

#include <stdio.h>
#include <stdarg.h>

void print_all(const char *first, ...) {
    va_list a; va_start(a, first);
    const char *s = first;
    while (s) { printf("%s\n", s); s = va_arg(a, const char *); }
    va_end(a);
}

int main(void) {
    print_all("a", "b", (char *)NULL);
    return 0;
}

Derleyici biçim öznitelikleri

GCC ve Clang, işlevinizin printf tarzı biçimlendirme kullandığını derleyiciye bildirmek için __attribute__((format(printf, 1, 2))) sunar.

Derleyici daha sonra biçim dizilerinizi derleme zamanında denetleyerek birçok hatayı yakalar.

#include <stdio.h>
#include <stdarg.h>

void logf(const char *fmt, ...)
    __attribute__((format(printf, 1, 2)));

void logf(const char *fmt, ...) {
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
}

int main(void) {
    logf("%d items\n", 3);
    return 0;
}

Daha güvenli seçenekleri tercih edin

Değişken sayıda bağımsız değişken hataya açık olduğundan mümkün olduğunda tür güvenli tasarımları tercih edin: açık bir dizi, bir yapı veya sabit parametreler geçirin.

Değişken sayıda bağımsız değişken kullanımını gerçek printf benzeri gereksinimlerle sınırlayın.

#include <stdio.h>

int sum_array(const int *a, int n) {
    int s = 0;
    for (int i = 0; i < n; i++) s += a[i];
    return s;
}

int main(void) {
    int nums[] = {1, 2, 3, 4};
    printf("%d\n", sum_array(nums, 4));
    return 0;
}

Sözleşmeyi belgeleyin

Derleyici değişken sayıda bağımsız değişkenin türlerini zorlayamadığından açık belgeler güvenlik ağınızdır.

Çağıranın tam olarak hangi türleri, kaç bağımsız değişkeni sağlaması gerektiğini ve listenin nasıl sona erdiğini belirtin.

#include <stdio.h>
#include <stdarg.h>

/* sum_ints(n, ...): pass exactly n int values */
int sum_ints(int n, ...) {
    va_list a; va_start(a, n);
    int s = 0;
    for (int i = 0; i < n; i++) s += va_arg(a, int);
    va_end(a);
    return s;
}

int main(void) {
    printf("%d\n", sum_ints(2, 5, 5));
    return 0;
}

Kapsamlı test yapmak

Hatalar sessizce gizlenebildiğinden değişken sayıda bağımsız değişken alan işlevleri birçok bağımsız değişken adedi ve türüyle test edin.

Sıfır bağımsız değişken veya en yüksek adet gibi sınır durumları çoğu zaman hataları ortaya çıkarır.

#include <stdio.h>
#include <stdarg.h>

int sum(int n, ...) {
    va_list a; va_start(a, n);
    int s = 0;
    for (int i = 0; i < n; i++) s += va_arg(a, int);
    va_end(a);
    return s;
}

int main(void) {
    printf("%d\n", sum(0));
    printf("%d\n", sum(1, 9));
    return 0;
}

Hızlı kontrol

Değişken sayıda bağımsız değişken türlerinin risklerini ne kadar anladığınızı test edin.

Özet

Değişken sayıda bağımsız değişken alan işlevlerin tehlikelerini öğrendiniz:

  • Derleyici, değişken sayıda bağımsız değişkenleri tür açısından denetlemez.
  • Yanlış türler, yanlış adetler ve hatalı sentinel'lar tanımsız davranışa neden olur.
  • Yükseltmeleri hatırlayın: küçük tam sayılar int türüne, float ise double türüne dönüşür.
  • Derleyici biçim özniteliklerini kullanın, sözleşmeyi belgeleyin ve mümkün olduğunda tür güvenli seçenekleri tercih edin.
Başlamak ücretsiz

Yapay zeka eğitmeniyle C öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
39
Dersler
144

Sıkça Sorulan Sorular

“Tür Güvenliği Kaygıları” dersi ücretsiz mi?

Evet — “Tür Güvenliği Kaygıları” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C Academy kursu toplamda 4 dersten oluşur.

“Tür Güvenliği Kaygıları” dersinde ne öğreneceğim?

Değişken bağımsız değişkenlerin riskleri C Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

C Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te C Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Tür Güvenliği Kaygıları” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu C Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her C Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. stdarg Makroları
  2. printf Benzeri İşlevler Yazma
  3. Tür Güvenliği Kaygıları
  4. Pratik Örnekler
← C Academy Sayfasına Dön