Möchte ISO C90 einhalten, aber wie?



  • Hallo,

    ich habe ein Programm und habe es soweit umgestellt, dass ich nun beim Kompilieren fast keine Warnungen mehr bekomme. Eine ist leider übrig geblieben, die ich auch gerne beseitigen würde. Der Kompilier meckert, dass mein Code nicht ISO C90 konform ist, da ich eine Variable deklariere nachdem schon Code geschrieben wurde. Wie kann ich dass in meinem konkreten Fall ab geschicktesten lösen?

    Hier der betroffene Code-Schipsel:

    Das Problem ist die Deklaration der String-Variable tempString[]. Diese Variable müsste ich ja eigentlich am Anfang deklarieren, doch zu diesem Zeitpunkt weiß ich noch nicht, wie groß der String sein soll.

    void getOneRule(int ruleNumber)
    {
    	char *ptr = procfs_buffer;
    	int pos = 0;
    	int i = 0;
    
    	for(i=1;i<ruleNumber;i++)
    	{
    		pos=strcspn(ptr,";");
    		ptr = (ptr+pos+1);
    	}
    
    	pos = strcspn(ptr,";");
    
    	//violation of ISO C90
    	//warning: ISO C90 forbids mixed declarations and code
    	char tempString[(pos+1)];
    
    	strncpy(tempString, ptr, (pos));
    	tempString[pos]='\0';
    

    thx



  • Hallo,

    du musst die Variable zu Beginn des Blocks deklarieren, wenn du im ISO C90 Mode kompilieren willst. Oder du aktivierst den C99 Modus bei deinem Compiler (-std=c99 bei gcc), dann kannst du es so lassen.

    EDIT: In dem Zusammenhang sollte man vllt. noch erwähnen, dass ISO C90 == ANSI C89 ist, wobei das z.B. beim gcc alles unter den Begriff ansi fällt.

    MfG

    GPC



  • In ISO C90 müssen lokale Variablen am Anfang der Funktion deklariert werden. Erts dann darf Code folgen.

    Zudem wäre char tempString[(pos+1)]; ein VLA (variable length array), welche auch erst ab C99 erlaubt sind.

    Da musst den Code also etwas überdenken 😉



  • wie wäre es mit malloc?

    void getOneRule(int ruleNumber)
    {
    
        char *ma = NULL; 
        ma = (char *) malloc((pos+1)* sizeof(char)); 
        free(ma);
    


  • Cool,

    habe gerade mein C Buch in der Hand und hatte auch überlegt es mit malloc() zu machen. ABER mein kleines Programm ist ein Kernelmodul! Was für eine Headerdatei brauche ich denn um malloc() verwenden zu können? stdlib.h oder? Ich glaube die kann ich im Kernelspace nutzen oder? Zumindest meckert der Kompiler.



  • Warum nicht einfach ein ausreichend großes lokales Array?



  • greif dir ein buch ueber kernel/linux systemprogrammierung?



  • slayer977 schrieb:

    Cool,

    habe gerade mein C Buch in der Hand und hatte auch überlegt es mit malloc() zu machen. ABER mein kleines Programm ist ein Kernelmodul! Was für eine Headerdatei brauche ich denn um malloc() verwenden zu können? stdlib.h oder? Ich glaube die kann ich im Kernelspace nutzen oder? Zumindest meckert der Kompiler.

    Ja die stdlib.h -> http://de.wikibooks.org/wiki/C-Programmierung:_stdlib.h

    Zum Kernelspace und Userspace .. keine Ahnung würde mich aber auch mal interessieren, denn in Kernelmodulen muss ja auch Speicher allokiert werden



  • evtl. noch alloca(). Ist aber nicht wirklich zu empfehlen (siehe manpage).



  • Wenn wir schon dabei sind...

    In Wikipedia steht

    In C ( anders als in C++) sollte man aber auf den cast verzichten, da dieser dann den Fehler verbirgt, welchen man bekommen könnte wenn man malloc() nicht Inkludiert hat.

    Wie ist das zu verstehen?



  • ich glaube in C könnte

    char *str = (char) malloc( 10 );
    

    ohne bekanntsein der Funktion malloc( ) wie eine lokale Funktionsdefinition aussehen!?

    Greetz, Swordfish



  • es gibt für den Kernelspace den Befehl kmalloc().

    http://ezs.kr.hsnr.de/TreiberBuch/html/a9387.html

    Habe es gerade mal in mein Programm verbaut. Mal schauen ob ich gleich nen Absturz erlebe 😉



  • Hm,

    mein Modul läuft einwandfrei, jedoch bekomme ich in der Logfile messages immer wenn kmalloc() benutzt wird Fehlermeldungen:

    Debug: sleeping function called from invalid context at mm/slab.c:2126
    Aug  9 21:16:31 slayer977 kernel: in_atomic():1, irqs_disabled():0
    Aug  9 21:16:31 slayer977 kernel:  [<c015c351>] __kmalloc+0x80/0x82
    Aug  9 21:16:31 slayer977 kernel:  [<e0a2346e>] getOneRule+0x2e/0x79 [s3]
    Aug  9 21:16:31 slayer977 kernel:  [<e0a2368e>] firewalling+0xce/0x5d6 [s3]
    Aug  9 21:16:31 slayer977 kernel:  [<c011be46>] __wake_up_common+0x39/0x59
    Aug  9 21:16:31 slayer977 kernel:  [<e0a23bc9>] main_hook+0x33/0x77 [s3]
    Aug  9 21:16:31 slayer977 kernel:  [<c0313039>] nf_iterate+0x60/0x84
    Aug  9 21:16:31 slayer977 kernel:  [<c0328b46>] ip_rcv_finish+0x0/0x2ca
    Aug  9 21:16:31 slayer977 kernel:  [<c0313312>] nf_hook_slow+0x4d/0xe6
    Aug  9 21:16:31 slayer977 kernel:  [<c0328b46>] ip_rcv_finish+0x0/0x2ca
    Aug  9 21:16:31 slayer977 kernel:  [<c032882c>] ip_rcv+0x1a6/0x4c0
    Aug  9 21:16:31 slayer977 kernel:  [<c0328b46>] ip_rcv_finish+0x0/0x2ca
    Aug  9 21:16:31 slayer977 kernel:  [<c0308e07>] netif_receive_skb+0x1cf/0x274
    Aug  9 21:16:31 slayer977 kernel:  [<c0308f13>] process_backlog+0x67/0xe4
    Aug  9 21:16:31 slayer977 kernel:  [<c030904b>] net_rx_action+0xbb/0x2bf
    Aug  9 21:16:31 slayer977 kernel:  [<e08f58d4>] ppp_async_process+0x1e/0x61 [ppp_async]
    Aug  9 21:16:31 slayer977 kernel:  [<c01282de>] __do_softirq+0x3e/0x8a
    Aug  9 21:16:31 slayer977 kernel:  [<c0105c29>] do_softirq+0x3e/0x42
    Aug  9 21:16:31 slayer977 kernel:  =======================
    Aug  9 21:16:31 slayer977 kernel:  [<c01283a5>] local_bh_enable+0x7b/0x7d
    Aug  9 21:16:31 slayer977 kernel:  [<c03051c2>] datagram_poll+0xc5/0xe3
    Aug  9 21:16:31 slayer977 kernel:  [<c0371552>] packet_poll+0xba/0x1ae
    Aug  9 21:16:31 slayer977 kernel:  [<c025f7ba>] normal_poll+0xe5/0x143
    Aug  9 21:16:31 slayer977 kernel:  [<c0259f3d>] tty_poll+0x57/0x61
    Aug  9 21:16:31 slayer977 kernel:  [<c02fdcc1>] sock_poll+0x12/0x14
    Aug  9 21:16:31 slayer977 kernel:  [<c019396e>] do_select+0x219/0x4c2
    Aug  9 21:16:31 slayer977 kernel:  [<c01935c1>] __pollwait+0x0/0x96
    Aug  9 21:16:31 slayer977 kernel:  [<c0193e0e>] sys_select+0x1df/0x38d
    Aug  9 21:16:31 slayer977 kernel:  [<c017b8d7>] vfs_write+0xb1/0x110
    Aug  9 21:16:31 slayer977 kernel:  [<c0103a51>] syscall_call+0x7/0xb
    


  • Ha!

    Ich habe nun das eine Flag veändert nun nu wird nicht mehr gemeckert.
    Hab's von GFP_KERNEL auf GFP_ATOMIC geändert. Ob es nun richtig ist, und ob es gut ist, dass ich keine Meldungen mehr bekomme. Wer weiß? 😉

    So sieht nun meine Speicherreservierung aus:

    dynamicArray = kmalloc((pos+1)*sizeof(char), GFP_ATOMIC);
    

    Und dann einfach wieder freigeben:

    kfree(dynamicArray);
    


  • slayer977 schrieb:

    Ha!

    Ich habe nun das eine Flag veändert nun nu wird nicht mehr gemeckert.
    Hab's von GFP_KERNEL auf GFP_ATOMIC geändert. Ob es nun richtig ist, und ob es gut ist, dass ich keine Meldungen mehr bekomme. Wer weiß? 😉

    Kommt darauf an was du machst.

    GFP_KERNEL
    Normale Allokation von Kernel-Speicher. Kann schlafen.

    GFP_ATOMIC
    Wird dazu verwendet, Speicher aus Interrupt-Handlern und anderem Code außerhalb von Prozeß-Kontexten zu allozieren. Schläft nie.

    http://www.oreilly.de/german/freebooks/linuxdrive2ger/get.html

    @Swordfish:
    Habe sogar hier was zum Thema casten von malloc in C gefunden:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-12864-and-start-is-0-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-.html



  • Was nehme ich denn da am besten? Habe jetzt ATOMIC.
    Was ich mache (vereinfacht) ist ich schaue in meinem ProcfsBuffer und suche nach dem ersten Auftauchen des Semikolons. Dann erzeuge ich diesen dynamicArray, der genau so lang sein soll, so dass alles von Anfang des Procfs Strings bis zum Semikolon da rein passt.

    Ist dafür ATOMIC nun gut?



  • codefrag schrieb:

    @Swordfish:
    Habe sogar hier was zum Thema casten von malloc in C gefunden:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-12864-and-start-is-0-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-.html

    Ja, so meinte ich das 😉

    Greetz, Swordfish



  • wieso kompilierst du denn nicht einfach als c99? Oder hast du vor dein Linux-Kernel-Modul mit irgendwas anderem als gcc zu kompilieren?


Log in to reply