ubuntuusers.de

warning: format not a string literal and no format arguments

Status: Gelöst | Ubuntu-Version: Xubuntu 14.04 (Trusty Tahr)
Antworten |

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6479

Wohnort: Hamburg

Ich bin gerade dabei, meine alten Quelltexte auf einen neueren PC zu bearbeiten. Dabei erhalte ich viele Warnungen, die ich ohne fremde Hilfe nicht abstellen kann. Hier mal ein Beispiel:

zk3.cpp: In member function ‘int MainWindow::ask_for_save(int)’:
zk3.cpp:898:41: warning: format not a string literal and no format arguments [-Wformat-security]
     switch( fl_choice( info, b0, b1, b2 ) ) {   // button index
                                         ^

Die zugehörige Funktion ist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//----------------------------------------------------------------------------
//      Ask the user what to do
//      reason: the reason for this request
//          0   exit (menu or window button)
//          1   new file or tree
//          2   shutdown from extern (SIGKILL SIGINT)
//              does not work when system goes down
//      returns 1 if running action should be canceled
int MainWindow::ask_for_save( int reason ) {
    const char  *info, *b0, *b1, *b2;

    switch( reason ) {
        case 1:
            info = "There are unsaved data! Do you really want to continue?";
            b0 = "Cancel";
            b1 = "Save+Cont.";
            b2 = "Continue";
            break;
        case 2:
            info = "There are unsaved data!";
            b0 = "Cancel";
            b1 = "Save+Exit";
            b2 = "Exit";
            break;
        default:
            info = "There are unsaved data! Do you really want to exit?";
            b0 = "Cancel";
            b1 = "Save+Exit";
            b2 = "Exit";
    }
    switch( fl_choice( info, b0, b1, b2 ) ) {   // button index
        case 1:
            if( !nf_save( 0 ) )                 // error when saving file
                return 1;
            break;
        case 2:
            break;
        default:
            return 1;
    }
    return 0;
}

Die angemeckerte Funktion ist die Bibliotheksfunktion fl_choice() aus dem FLTK Toolkit. Was Google mir dazu liefert, hilft mir nicht wirklich weiter.

Gibt es da einen Trick oder kann man zumindest temporär für diese Funktion die Warnung zu unterdrücken?

p.s. ich habe dem Compiler keine besonderen Optionen übergeben. Das ist bei dieser Version so vor eingestellt.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17599

Wohnort: Berlin

Ich bin auch überfragt und nutze ewig und 3 Tage weder C noch C++.

Die bruchstückhaften Gewissheiten und Vermutungen, die ich beisteuern kann, sind, nachdem ich frage, wieso Du die Warnungen loswerden willst, folgende:

1
2
3
4
5
6
int fl_choice	(	const char * 	fmt,
const char * 	b0,
const char * 	b1,
const char * 	b2,
 	... 
)		
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Shows a dialog displaying the fmt message, this dialog features up to 3 customizable choice buttons.

Note
Common dialog boxes are application modal. No more than one common dialog box can be open at any time. Requests for additional dialog boxes are ignored.
#include <FL/fl_ask.H>
Parameters
[in]	fmt	can be used as an sprintf-like format and variables for the message text
[in]	b0	text label of button 0
[in]	b1	text label of button 1
[in]	b2	text label of button 2
Return values
0	if the first button with b0 text is selected or another dialog box is still open
1	if the second button with b1 text is selected
2	if the third button with b2 text is selected
  1. cpp: Ist die Absenderkennung des C-Präprozessors.

  2. Ein Stringliteral sieht so aus: "Foobar". Info dagegen ist ein Char-Zeiger (auf ein variables Stringliteral).

  3. Ein sprintf-like-Format ist etwas wie "Sie haben %d Euro und wollen %4.2f Liter Kaffee kaufen." Das keine Formatstringelemente in den verschiedenen Möglichkeiten, die info annehmen kann, sollte m.E. aber kein Problem darstellen. Die Position des Warnungscarets deutet aber darauf hin, dass nach dem b2 noch etwas erwartet wird. Das sind wohl die Elemente variabler Anzahl, die dem Formatstring übergeben werden sollen (hier 0). Wieso diese nicht 0 sein dürfen verstehe ich aber nicht. Womöglich eine falsche Prüfreihenfolge, also dass zuerst diese gesucht und angemeckert werden, bevor der Formatstring auf Marker für solche analysiert wird.

  4. Du könntest mal damit experimentieren eine Dummyvariable, eine 0 oder einen leeren String zusätzlich zu übergeben oder das "There", welches alle 3 Meldungen teilen, oder irgendwas, das nicht benötigt wird, aber das ist wildes Probieren und wenn es klappt ist das ein hervorragender Anlass, dem Quellcode einen Kommentar zuzufügen.

Solche Formatstringanalysen soll v.a. Fehler abfangen, wenn der Parameter nicht zum angegebenen Format passt oder wenn zu wenige Parameter übergeben werden - wenn aber zuviele angemeckert werden sollte man sich auch nicht wundern.

p.s. ich habe dem Compiler keine besonderen Optionen übergeben. Das ist bei dieser Version so vor eingestellt.

Arbeitest Du mit einem Makefile, mit autoconf oder sowas? Wie startest Du denn den Buildprozess? Gibt es Systemweite Defaults oder Userweite?

Ich würde ja auf -Wno-format-security tippen, aber das nur für eine Quellcodedatei ein- und dann wieder auszuschalten, da wüsste ich nicht wie das geht (also mit einem Makefile geht das wohl, aber nicht mit mir aus dem Handgelenk).

Bei dieser Version von was ist das so?

barcc

Avatar von barcc

Anmeldungsdatum:
13. Juli 2007

Beiträge: 696

Wohnort: Dortmund

Eine Möglichkeit wäre:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//----------------------------------------------------------------------------
//      Ask the user what to do
//      reason: the reason for this request
//          0   exit (menu or window button)
//          1   new file or tree
//          2   shutdown from extern (SIGKILL SIGINT)
//              does not work when system goes down
//      returns 1 if running action should be canceled
int MainWindow::ask_for_save( int reason ) {
    int  choice = 0;

    switch( reason ) {
        case 1:
            choice = fl_choice( "There are unsaved data! Do you really want to continue?",
                                "Cancel",
                                "Save+Cont.",
                                "Continue" );
            break;
        case 2:
            choice = fl_choice( "There are unsaved data!",
                                "Cancel",
                                "Save+Exit",
                                "Exit" );
            break;
        default:
            choice = fl_choice( "There are unsaved data! Do you really want to exit?",
                                "Cancel",
                                "Save+Exit",
                                "Exit" );
    }
    switch( choice ) {   // button index
        case 1:
            if( !nf_save( 0 ) )                 // error when saving file
                return 1;
            break;
        case 2:
            break;
        default:
            return 1;
    }
    return 0;
}

Oder du tauscht Zeile 31 durch folgende aus:

1
switch( fl_choice( "%s", b0, b1, b2, info ) ) {   // button index

"sprintf-like format"-Argumente sollten immer String-Literale sein, damit beim Funktionsaufruf sichergestellt werden kann, dass die variable Argumente auch zum Format-String passen.

(Ich hab den Code nicht getestet, bin mir aber ziemlich sicher, dass die Warnung verschwindet)

Solche Warnungen sollte man nicht ausstellen, sondern (wie du getan hast) nach dem Grund suchen, wenn man robusten und sicheren Code schreiben will.

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6479

Wohnort: Hamburg

Arbeitest Du mit einem Makefile ... ?

Oh, fast hättest Du mich erwischt. Ich arbeite tatsächlich mit einem Makefile und hatte da aufgrund einer anderen Diskussion ein "-Wall" eingefügt. Das hatte ich vergessen. Das scheint aber je nach Compiler Version unterschiedlich viele Optionen zusammenzufassen.

@barcc Dein erster Vorschlag gefällt mit gar nicht, denn das ist ja fast das wo ich herkomme. Allerdings war das über den gesamten Text verstreut, was unübersichtlich ist.

Aber

    switch( fl_choice( "%s", b0, b1, b2, info ) ) {   // button index

das war die Lösung!

Danke.

Solche Warnungen sollte man nicht ausstellen,

Das sehe ich zwar auch so, aber es gibt immer wieder mal Situationen, wo einem der Grund bekannt ist, man daran nichts ändern kann oder will. Mein letzter Fall dieser Art war allerdings noch zu Windows Zeiten mit dem Borland C Compiler. Da gab es dann sowas wie "#pragma warn", oder so ähnlich.

Ein Stringliteral sieht so aus: "Foobar". Info dagegen ist ein Char-Zeiger (auf ein variables Stringliteral).

Jetzt ist mir der Unterschied auch klar.

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6479

Wohnort: Hamburg

Um das Thema abzurunden.

Nachdem ich noch so eine (für mich) kryptische Warnung

warning: operation on ‘...’ may be undefined [-Wsequence-point]

erhielt, hatte ich weiter gesucht und Diagnostic Pragmas gefunden. Damit kann man bestimmte Warnungen temporär unterdrücken.

Aber glücklicherweise konnte ich die Ursache doch noch finden und beseitigen. Aber statt "undefined" hätte in meinem Fall "doppelt" besser gepasst.

Antworten |