2011-08-25 25 views
10

numCheck 1-1000 arasında bir sayıdır. Bu kod, yalnızca charcheck'te sprintf sonuçlarını topladığımda bana bir segfault verir. Sprintf'i sonuçları kullanmadan kullanırsam, bir seg hatası almıyorum. Burada neler oluyor?sprintf'i Bölümleme Hata

char * numString; 
int charcheck = sprintf(numString, "%d", numCheck); 

cevap

7

sprintf için kendi belleğinizi sağlamanız gerekir. Ayrıca, sprintf ziyade snprintf kullanmayın:

char buf[1000] = {0}; 

snprintf(buf, 999, ....); 

Alternatif dinamik bellek ayırabilir:

char * buf = new char[BUFSIZE]; 
snprintf(buf, BUFSIZE-1, ...); 
/* ... */ 
delete[] buf; 
+0

Sonuçları neden topladığımda tam olarak neden çalışıyor? – syl

+0

Bu tanımlanmamış bir davranış. Bazen tanımlanmamış davranış tam olarak beklediğiniz gibi davranır, ki bu muhtemelen en kötü durumdur. –

+1

Neden sprintf' üzerinden snprintf' önerirsiniz? – Kevin

1

sprintf ilk argümanı geçerli tampon göstermelidir. Bir char* var, ancak çöp atıyor.

için kodunuzu değiştirin

:

numString aslında geçerli bir tampon işaret
char numString[80] = { }; 
int charcheck = sprintf(numString, "%d", numCheck); 

Böylece (bu örnekte 80 karakter, tüm unsurları olan 0'a ilklendirildikten). Eğer geçmesi tampon boyutundan birini çıkarmak

const int bufsize = 80; 
char numString[bufsize] = { }; 
int charcheck = snprintf(numString, bufsize - 1, "%d", numCheck); 

Bildirimi:

Ayrıca böylece tampon taşmaları önlemek yardımcı olacaktır buna da tampon boyutunu geçirebilmesi snprintf kullanmak iyi olurdu snprintf için, son dizeyi kullanmasını istemediğinizden emin olun, istediğiniz dizgenin sonunu göstermek için NULL olduğundan emin olun.

+0

Karakterleri geçirdiğim tam sayı boyutunu bulabildiğim herhangi bir yol var mı, bu yüzden 80 gibi keyfi bir değer kullanmak yerine doğru miktarda alan ayırabiliyorum? – syl

+0

@user, fazladan alan ayırmak için muhtemelen daha verimli olacaktır (bir karakterin depolayacağınız türe göre bir maksimum karakter olabileceğini hesaplayabilirsiniz). Sadece numaranızın en büyük sayısından daha küçük olanı hesaplarsınız (örneğin, 10'dan küçükse (ancak her zaman '> 0' ise, 1 puan), 100'den küçükse 2 haneli, vs.). Ancak yığında yer ayırmak, sabit bir zaman gerektirir (ve bu durumda çok küçük bir sabit), çünkü "num numtring [9999999999999]" gibi bir şey yapmazsanız iyi olmalısınız. –

0

Sen sprintf interal işleyiş sizin durumunuzda bir işaretçi için varsayılan değerdir NULL başvurmak için çalışıyoruz Senin durumunda gibi

char numString[50]; 
int charcheck = sprintf(numString, "%d", numCheck); 

sonucu alanı ayırmaya gerek.

1

sprintf için ilk parametre olarak verilen işaretçinin, biçimlendirilmiş dizeyi sprintf yazması gereken bir bellek konumuna işaret etmesi bekleniyor. Bu durumda

Eğer biçimlendirilmiş dize için ayrılan bazı belleğe işaret edecek numString başlatılamadı. numString başlatılmamış olduğundan, herhangi bir yere işaret edebilir ve durumunuzda biçimlendirilmiş çıktıyı bu konuma yazmaya çalışmak bölümleme hatasına neden olur.

0

yapmak için en basit bir şey

char numString[80] = { }; 

Seth İsa ve Kerrek önerdiği, örneğin, yukarıdaki gibi bir dizi kullanmaktır.

Sanırım sth'nin son cevabı iyi bir açıklama: "sprintf'in ilk parametresinin, sprintf'in biçimlendirilmiş dizeyi yazması gereken bir bellek konumuna işaret etmesi bekleniyor." Yani ayrı dizesi için bellek tahsisi zorlayacaktır karakter dizisi, kullanarak, ayrıca bu kullanabilirsiniz:

char *numstring = (char*) malloc(80); 

Bu artık gerektiğinde açıkça ayrılan bellek boşaltmak izin vermelisiniz.

İlgili konular