2016-03-21 17 views
-2

Tüm kodlarımı yazdığım Ubuntu'da sorunları olmayan bir üniversite projesi için bazı C kodu yazdım. İşaretlendiğinde öğretmen çıktı üretmediğini söyledi. Yine de benim için çalışıyor, ancak Windows'da çalıştırdığımda kodumun bozulduğunu bulduğumda, öğretmenin Windows'da kodumu çalıştırdığına dair şüphem doğru çıktı. Sorunu çözdüm. (I Daha sonra, örneğin, içeren başka bir karakter dizisi (char grade_str[3]) içeriğini alırC dizisi Windows & Ubuntu üzerinde farklı bir şekilde ele alındı ​​

char grade[2]; 

, "B3", içine kopyalanır:

I karakter dizisi vardır: Aşağıdaki oldu

strcpy(grade, grade_str); 

dize grade (sözde şimdi eşit "B3") için notlarının tam bir dosyaya karşılaştırılır() strcmp kullanarak bir maç almak için) bu bir hata farkındayım. Windows'da (tam olarak 7) dışında, asla eşleşmez, çünkü grade Bu, "B30 ~ $" gibi bir şeye benziyor. Dizi sadece 2 bayt olduğundan, bu olmamalı. Sorunun neredeyse hem dize hem de boş bir bayt için yeterli alan sağlamamasından ve char grade[3];'un gerçekten durumu düzeltmesinden kaynaklandığını biliyorum. Bununla birlikte, Windows veya Ubuntu'da derleme yaparken neden hata yapamadığımı ve neden her zaman Ubuntu'da her zaman mükemmel çalıştığını bilmek istiyorum. Şu andan itibaren Windows VE Linux'taki kodumu kontrol etmek zorunda kalacağımı hissediyorum ... ya da bu hataların derleyici tarafından düzgün bir şekilde yükseltildiğinden emin olmanın bir yolu var mı, bir çeşit süper uyanık mod? kullanılan

Derleyiciler:

  • Ubuntu: gcc sürüm 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
  • Windows 7: Sadece bu yüzden oldukça emin, bunu güncellenmiş mingw32 gcc 4.7
+0

O Ok C – wRAR

+0

, teşekkür gibi dillerde derleme sırasında tüm bellek erişimi hataları yakalamak imkansızdır. Mümkün olduğunu düşünürdüm ... Şimdi bu soruyu sileceğim, yani eğer başka birinin aynı sorusu varsa, tekrar tekrar sormak zorunda kalacaklar. – Totem

+3

Gösterilen başlangıç ​​yok. char notu [2]; 'sadece bir beyan veya geçici bir tanımdır. Bir char [2] '2' char's bir dizi, ama 3 'chars' harekete! – Olaf

cevap

3

Aslında Linux üzerinde düzgün çalışmadığını anlamanız gerekir ... Olan şey, boş bir karakter bulana kadar hafızada okumaya devam etmesidir.

Belki de Linux'ta şansınız oldu ve dizinin yanındaki bayt sıfırdı ve Windows'da şanslı değildiniz.

Ama yine de kötü programlama var, her zaman, Ubuntu verir

size çalışmıyor bir örnek vermek gerekirse ... boş başka bunu bulmak çok zor hataların ortaya çıkmasına neden olabilir, dize sonlandırıldı olmalı değişkenleri saklamak için hafızada bir oda var. Yani diziniz gibi bir veya iki değişkeniniz var. Bir gün başka bir değişken ekleyeceksiniz ve Linux dizinin ardına saklayacaktır. Sonra programınızın başlangıcında işe yarayabilir, sonra yeni değişkeninizi başlatacaksınız, sonra dizinize eriştiğinizde çökecektir ...

+0

Teşekkürler, bunun kötü olduğunun farkındayım .. ama enteresan buldukları girişi değiştirdiğim önemli olan Ubuntu'nun içinde çalışır. Windows bunlardan hiçbirine sahip değil – Totem

+2

Yanlış bir programın bazı durumlarda neden işe yaradığı önemli değil, hala yanlış. – wRAR

+1

@Totem belki 1000 kez "çalışacak" ancak 1001'inci kez başarısız olacaktır. Ya da derleyicinizi en son sürüme güncelledikten sonra her zaman başarısız olur. _undefined behaviour_. –

1

Çalışma zamanında bu tür hataları yakalamak için clang adres dezenfektanı kullanabilirsiniz.

#include <string.h> 

int main() 
{ 
    char grade[2]; 
    char grade_str[] = "B0"; 

    strcpy(grade, grade_str); 

    return 0; 
} 

Sen -fsanitize=address ile derlemek olabilir: Eğer programı çalıştırırsanız

clang -fsanitize=address main.c 

, bazı hata ayıklama bilgi ile kıracak

Let Eğer arabası koduna sahip varsayalım.

==19588==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd9bcf7422 at pc 0x455bc0 bp 0x7ffd9bcf7350 sp 0x7ffd9bcf6b08 
WRITE of size 3 at 0x7ffd9bcf7422 thread T0 
==19588==WARNING: Trying to symbolize code, but external symbolizer is not initialized! 
    #0 0x455bbf (/tmp/a.out+0x455bbf) 
    #1 0x47afd1 (/tmp/a.out+0x47afd1) 
    #2 0x7fa15d228ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4) 
    #3 0x47ac3c (/tmp/a.out+0x47ac3c) 
[... and so on] 

Sen clang's documentation

+0

'strcpy (grade, grade_str) - derecesine dönüşür;' Ve bir dönüşüm sorunu elde edersiniz ‘uzun int’ den ‘int’ dönüşümü değerini değiştirebilir '' – Michi

+0

@Michi Çıkarma işlemini kaldırdım. OP hatasını çoğaltmak gerekli değildi. – user3188346

2

BOŞ-sonlandırılmış olmayan dizeleri üzerinde dize işlevleri çağıran içinde daha fazla bilgi bulabilirsiniz ("UB") undefined behavior olduğunu. UB, ne olacağı bilinmemektedir. Çalışabilir veya işe yaramayabilir. Senin durumunda, Linux üzerinde çalışıyor, Windows üzerinde çalışmıyor. UB'ye sahip olduğunuzda, ne olacağını tahmin edemezsiniz.

UB daima dikkat ve dil UB sonuçlanır şey yapmaktan engel olmaz C. farkında olmak bir şeydir. Kendine dikkat etmelisin. Clang ve GCC gibi derleyiciler bunu tespit etmenize yardımcı olabilir, ancak hiçbir garanti yoktur.

İlgili konular