Sejak memutakhirkan ke Xcode 3.2.1 dan Snow Leopard terbaru, saya telah mendapatkan peringatan
"format bukan string literal dan tanpa argumen format"
dari kode berikut:
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
NSLog([NSString stringWithFormat:@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]]);
}
Jika errorMsgFormat
adalah NSString
dengan format specifiers (misalnya: "print me like this: %@"
), apa yang salah dengan di atas NSLog
panggilan? Dan apa cara yang disarankan untuk memperbaikinya sehingga peringatan tidak dibuat?
objective-c
warnings
string-formatting
nslog
Alexi Groove
sumber
sumber
NSLog()
dapat mengambil satu argumen, ketika string format tidak berisi penentu format.Xcode mengeluh karena ini adalah masalah keamanan.
Berikut kode yang mirip dengan milik Anda:
Pernyataan NSLog terakhir itu akan menjalankan yang setara dengan ini:
Itu akan menyebabkan NSLog mencari satu argumen string lagi, tetapi tidak ada satu pun. Karena cara kerja bahasa C, ia akan mengambil beberapa penunjuk sampah acak dari tumpukan dan mencoba memperlakukannya seperti NSString. Ini kemungkinan besar akan merusak program Anda. Sekarang string Anda mungkin tidak memiliki% @ di dalamnya, tetapi suatu hari nanti mungkin. Anda harus selalu menggunakan string format dengan data yang Anda kontrol secara eksplisit sebagai argumen pertama ke fungsi yang mengambil string format (printf, scanf, NSLog, - [NSString stringWithFormat:], ...).
Seperti yang ditunjukkan Otto, Anda mungkin harus melakukan sesuatu seperti:
sumber
Jawaban akhir: Seperti yang dikatakan Jon Hess, ini adalah masalah keamanan karena Anda mengirimkan string APA PUN ke fungsi yang mengharapkan string format. Artinya, ini akan mengevaluasi semua penentu format DALAM string apa pun. Jika tidak ada, luar biasa, tetapi jika ada, hal buruk bisa terjadi.
Hal yang tepat untuk dilakukan, kemudian, adalah MENGGUNAKAN string format secara langsung, misalnya
Dengan begitu, meskipun ada penentu format di myNSString, mereka tidak dievaluasi oleh NSLog.
sumber
Saya tidak merekomendasikan penggunaan ini secara khusus, karena peringatan IS adalah peringatan nyata .. dalam penggunaan bahasa yang dinamis, dimungkinkan untuk melakukan sesuatu secara runtime ke string (yaitu memasukkan informasi baru atau bahkan merusak program) .. Namun mungkin saja untuk menekan secara paksa jika Anda TAHU seharusnya seperti ini dan Anda benar-benar tidak ingin diperingatkan ..
#pragma GCC diagnostic ignored "-Wformat-security"
Akan memberi tahu GCC untuk sementara mengabaikan peringatan kompilasi .. Sekali lagi ini tidak menyelesaikan apa pun tetapi mungkin ada kalanya Anda tidak dapat menemukan cara yang baik untuk benar-benar memperbaiki masalah.
EDIT: Pada dentang, pragma telah berubah. Lihat ini: https://stackoverflow.com/a/17322337/3937
sumber
Cara tercepat untuk memperbaikinya adalah dengan menambahkan
@"%@",
argumen pertama keNSLog
panggilan Anda , yaitu,Padahal, Anda mungkin harus mempertimbangkan jawaban Sixteen Otto.
sumber
Saya baru saja melewati nol untuk meniadakan peringatan, mungkin itu akan berhasil untuk Anda?
NSLog (myString, nil);
sumber
myString
, yang pertama akan baik-baik saja, tetapi yang kedua akan mengambil sampah dari tumpukan. Daftar substitusiNSLog()
adalah tidak pernahnil
-terminated, @Sold. Ada dua opsi untuk mengetahui berapa panjang daftar argumen: nilai sentinel, atau apa yang digunakan dalamprintf()
dan keluarga - argumen lain yang memungkinkan penghitungan nomor (misalnya, dengan menghitung penentu format).Jika Anda ingin menghilangkan peringatan "format bukan string literal dan tidak ada argumen format" sekali dan untuk selamanya, Anda dapat menonaktifkan pengaturan peringatan GCC "Typecheck Calls to printf / scanf" (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) di pengaturan build target Anda.
sumber
NSLog () mengharapkan format string, yang diteruskan hanyalah string. Anda tidak perlu menggunakan stringWithFormat :, Anda cukup melakukan:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
Dan itu akan membuat peringatan itu hilang.
sumber
FWIW, ini juga berlaku untuk iPhone dev. Saya melakukan pengkodean terhadap 3.1.3 SDK, dan mendapatkan kesalahan yang sama dengan masalah yang sama (bersarang stringWithFormat di dalam NSLog ()). Sixten dan Jon sedang mencari uang.
sumber
Memberi tahu siapa pun menggunakan
appendFormat
on NSMutableString juga dapat menyebabkan peringatan ini muncul jika mencoba meneruskan dalam string yang diformat seperti ini:Jadi untuk menghindari peringatan ini, ubah yang di atas menjadi ini:
Lebih ringkas dan lebih aman. Nikmati!
sumber
sumber
stringWithFormat
berlebihan di sini ketika Anda bisa melakukannyaNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])