2012-08-29 27 views
6

Küçük C kitaplığımda hata raporlama işlevselliği var Yazıyorum. Hata mesajlarına bilgi gömülmesine izin vermek için düz error işlevine ek olarak bir errorf işlev sağlamak istiyorum. Printf etrafındaki sargılarda uyarıdan kaçının

/* 
* Prints a formatted error message. Use it as you would use 'printf'. See the 
* 'sio_error' function. 
*/ 
void sio_errorf(const char *format, ...) { 
    // Print the error prefix       
    if (g_input == STDIN) fputs("error: ", stderr); 
    else fprintf(stderr, "%s: ", g_progname); 

    // Pass on the varargs on to 'vfprintf'. 
    va_list arglist; 
    va_start(arglist, format); 
    // This may produce the following warning -- ignore it: 
    //  warning: format string is not a string literal 
    vfprintf(stderr, format, arglist); 
    va_end(arglist); 
    fputc('\n', stderr); 
} 
sorun, ben bu uyarıyı olsun

( -Weverything anahtarı ile clang 4.0 ile derleme):

uyarı: biçim dizesi neden anlamak değişmez bir dize

değil Bunu yapmak kötü olur. Bu uyarıdan kurtulabilmemin bir yolu var mı? Bir şekilde format argümanının sio_errorf argümanının bir string literal olmasını zorunlu kılabilir miyim, böylece derleyici her zaman olacağını ve sadece bunu geçeceğimi biliyor mu?

-Wno-format-nonliteral'u kullanabileceğimi biliyorum, ancak yalnızca başka insanlar da el ile derledikleri takdirde, bunu yapmazlar. Uyarı kodunu susturup kaynak kodunda bir şey tercih ederim. dize Ben sio_errorfgeçirilen eğer

İdeal hala aslında bir hazır değil uyarı alacağı, ancak bunun mümkün olup olmadığından emin değilim. GCC veya yakınları birini kullanıyorsanız

+1

Hangi derleyici ve ne sürümü, kullandığınız:

itme kullanımı/pop gibi bir şeyle özgün mecrasına restorasyon sağlayacak? –

+0

Clang ('-v' bana" Apple clang version 4.0 "yazıyor), gcc'nin de aynı uyarıyı verdiğinden eminim. – mk12

cevap

9

, beyanda bir özelliği deneyin:

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

bir tanımına öznitelik eklemek için, bu kullanabilirsiniz:

__attribute__((format(printf, 1, 2))) 
    static void sio_errorf(const char *format, ...) { 
     .... 
+2

İyi fikir! Bu, özellikle bu durumlar için GCC tarafından sağlanmaktadır. – Linuxios

+0

Bu, sadece başlıktaki fonksiyon prototipinde devam ediyor mu? Tanımı değil mi? – mk12

+0

@ Mk12, bir tanıma da uygulayabilirsiniz: __attribute __ ((format (printf, 1, 2))) statik void sio_errorf2 (const char * biçimi, ...) {\ n ... '. ancak öznitelik çeviri içinde görünmüyorsa, derleyici formatınızı/parametrelerinizi kontrol etmeyecektir. (cevabı güncelleyecektir) – justin

8

Birçok derleyici, uyarı seviyelerini bir şekilde ayarlayabilmenizi sağlar. Örneğin, gcc, derleyiciyi çağırırken komut satırında -W bayraklarıyla denetim yapılmasına izin verir.

Umarım böyle bir program beri kullandığınız derleyici var:

#include <stdio.h> 
int main (void) { 
    char *s = "xyzzy\n"; 
    printf (s); 
    return 0; 
} 

sen (siz -Wformat ve -Wformat-nonliteral birlikte uyarı etkinleştirdikten varsayarak) tarif kesin iletisi oluşturur. Aradığınız olacağını

belirli komut satırı argümanı: O işlevlerde olmayan dizeler kullanımı konusunda şikayetleri önleyecektir

-Wno-format-nonliteral 

.

#include <stdio.h> 
#pragma GCC diagnostic ignored "-Wformat-nonliteral" 
int main (void) { 
    char *s = "xyzzy\n"; 
    printf (s); 
    return 0; 
} 
#pragma GCC diagnostic warning "-Wformat-nonliteral" 

Eğer derleme ise:

Ancak, aynı zamanda pragmas ile içinde sinek kodunuzu belirli tanı mesajlarının eğilim belirlemenizi sağlar böylece daha ince taneli bir şey arıyor olabilir ile numaralı uyarıyı göremezsiniz, çünkü gcc'nin main işlevi için bu uyarıyı dikkate almamasını söylediniz.itmek ve teşhis durumunu açılacaktır

#pragma GCC diagnostic push 
#pragma GCC diagnostic pop 

: Ben çalıştırmak olandan gcc'nin

Sonraki sürümlerinde aşağıdaki seçenekleri kullanabilirsiniz. Bu, yukarıdaki uyarıyı hata olarak yapılandırabileceğiniz kodumun üstesinden gelir - ikinci pragma bu uyarıyı değiştirir.

#include <stdio.h> 
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wformat-nonliteral" 
int main (void) { 
    char *s = "xyzzy\n"; 
    printf (s); 
    return 0; 
} 
#pragma GCC diagnostic pop 
+0

Cevabınızın ilk kısmı için - özür dilerim, bildiğimi bilmeliydim '-Wo-format-nonliteral'. Yine de herkesi zorlayamam. -Weverything' ile derleyebilmeyi ve hiçbir uyarı almamayı tercih ederim. – mk12

+0

Cevabınızın ikinci kısmı, istediğim gibi görünüyor. Şu anda Justin'in cevabıyla karşılaştırıyorum. – mk12