char, *char, strcpy - Fortran-Programmierer sucht C-Hilfe...
-
Hallo zusammen,
ich programmiere nur in Fortran, habe deshalb von C null Ahnung, habe aber ein Problem mit der C-Funktion strcpy und der Sache mit Zeigern und so, da ich dass nicht kenne. Vielleicht kann mir jemand freundlicherweise helfen.
Ich rufe mit Fortran (da kenn ich mich ja aus) eine C-Routine auf, an die ein String übergeben wird. In Fortran wird auch die gefortderte /0 drangehängt, so dass die Übergabe korrekt erfolgt.
Das Problem, dass sich mir jetzt stellt ist, dass der Intel-Thread Checker (Parallelisierung mit OpenMP) jetzt einen Fehler in der C-Funktion gefunden hat, den ich mir nicht erklären kann.
Das Problem liegt laut Thread-Checker in der Zeile 23
strcpy(textfilename,file);
Es wäre dort etwas "undefined in the serial code". Der Fortran Code übergibt an den char *file korrekt, aber irgendwas scheint nicht zu stimmen. ich kompiliere auch mit dem icc, so dass es eigentlich gehen sollte. Das Programm läuft auch, aber die Fehlermeldung macht mich doch ein wenig stutzig.
Hier nun der Code:
void CCsmoke3dheader(char *file,int *is1, int *is2, int *js1, int *js2, int *ks1, int *ks2){ FILE *binfile,*textfile; int nxyz[8], VERSION=0; char textfilename[1024]; nxyz[0]=1; nxyz[1]=VERSION; nxyz[2]=*is1; nxyz[3]=*is2; nxyz[4]=*js1; nxyz[5]=*js2; nxyz[6]=*ks1; nxyz[7]=*ks2; binfile=fopen(file,"wb"); if(binfile==NULL)return; fwrite(nxyz, 4,1,binfile); fwrite(nxyz+1,4,7,binfile); fclose(binfile); strcpy(textfilename,file); strcat(textfilename,".sz"); textfile=fopen(textfilename,"w"); fprintf(textfile,"%i\n",VERSION); fclose(textfile); }
Schon mal vielen Dank für die Hilfe!
Christian
-
wo ist denn die Variable file deklariert???
-
Probier mal strncpy. Damit kannst du die maximale Zahl an zu kopierenden Zeichen angeben:
char textfilename[1024]={0}; //zur Sicherheit mit Nullen initialisieren strncpy(textfilename,file,1023); //maximal 1023 Zeichen kopieren, eine abschließende 0 ist gewährleistet
Nur für den Fall, dass da doch keine 0 mitkommt.
-
Wenn der Thread-Checker das sagt, dann nehmen wir einmal an, daß er Recht hat:
Das würde bedeuten, daß dein Parameter file unter Umständen irgendwo hinzeigt,
wo aber noch nicht der erwartete Wert steht. Ich kenn mich mit OpenMP nicht aus,
aber könnte es sein, daß der Wert hinter file von einem anderen Thread gesetzt wird?Das wäre eine Erklärung, und die Lösung wäre wahrscheinlich auch nicht schwer.
ZB gibt es in OpenMP eine barrier-Anweisung, die auf die anderen Threads wartet.Zeig mal den Code her, der die Funktion aufruft.
-
Vielen Dank erstmal für die Antworten!
Ich habe den Tipp von _matze getestet, immer noch das gleiche Problem.
Also mit dem Aufruf der Funktion void CCsmoke3dheader ist es wie folgt: die Funktion wird über ein Interface angesteuert, das wie folgt lautet:
interface subroutine smoke3dheader(file,is1,is2,js1,js2,ks1,ks2) !DEC$ ATTRIBUTES C :: SMOKE3DHEADER !DEC$ ATTRIBUTES REFERENCE :: FILE,IS1,IS2,JS1,JS2,KS1,KS2 character(len=*), intent(in) :: file integer, intent(in) ::is1,is2,js1,js2,ks1,ks2 end subroutine smoke3dheader
Über ein #define wird vorher die C-Funktion CCsmoke3dheader so umbenannt, dass das mit dem _ passt (je nachdem welche Kompileroption gewählt wird).
Das Interface wird dann mit der kompilierten C-Datei gelinkt, somit ist die Funktion dann in Fortran mit dem Namen SMOKE3DHEADER ansprechbar.Aufgerufen wird die Funktion dann in Fortran mit
CALL SMOKE3DHEADER(TRIM(FN_SMOKE3D(1,NM))//CHAR(0),0,M%IBAR,0,M%JBAR,0,M%KBAR)
Der erste Parameter bedeutet, dass der Dateiname ohne weitere Leerzeichen übergeben wird, durch das //CHAR(0) wird noch das für C notwendige Steuerzeichen (also die Nulltermination) mit übergeben, somit passt das. Die Länge des übergebenen CHARACTER-Strings ist auch nicht das Problem, maximal sind es 80 Zeichen in Fortran (wurde so deklariert). Die restlichen Werte sind Integerwerte, auch alles passend.
Mit OpenMP und den Threads passt das auch, da dieser Aufruf seriell erfolgt, also keine Threadumgebung oder ähnlich.
Der Intel Thread Checker gibt folgende Meldung aus:
OpenMP* -- undefined in the serial code (original program) at "isob.c":2132 with "dump.f90":744
Zeile 2132 in isob.c ist die oben angesprochene mit dem strcpy, die Zeile 744 in dump.f90 ist die Zeile
CALL SMOKE3DHEADER(TRIM(FN_SMOKE3D(1,NM))//CHAR(0),0,M%IBAR,0,M%JBAR,0,M%KBAR)
Wo in der isob.c welche Variablen definiert werden, weiß ich nicht, da ich mich dort nicht auskenne. Die isob.c Datei ist unter http://code.google.com/p/fds-smv/source/browse/trunk/FDS/trunk/FDS_Source/isob.c einsehbar, Zeile 2132 ist die Zeile, um die es geht.
Grüße und Danke für die Hilfe
Christian
-
Ich befürchte, daß ich dein Problem nicht lösen kann.
Was mir aber aufgefallen ist:lso mit dem Aufruf der Funktion void CCsmoke3dheader ist es wie folgt: die Funktion wird über ein Interface angesteuert, das wie folgt lautet:
(...)Zeile 7 bedeutet wahrscheinlich, daß der String beliebig lang sein darf.
Obwohl Pfadangaben auf üblichen Systemen begrenzte Längen haben, würde ich matzes
Vorschlag empfehlen, um Pufferüberläufe auszuschließen. Daran liegt's aber, wie du
schon gesagt hast, offenbar nicht.Aufgerufen wird die Funktion dann in Fortran mit
(...)Das sieht sinnvoll aus. Aber du bist der Fortran-Kenner, und wenn du sagst, daß
das so stimmt, dann wird's schon so sein. Ich für meinen Teil finde den C-Code an sich
unproblematisch. Glaube nicht, daß dein Problem an deinem C-Code liegt.Der Intel Thread Checker gibt folgende Meldung aus:
(...)Was meint er eigentlich mit serial code?
Wenn der Thread-Checker jammert, du aber gar keine Threads verwendest, ist das seltsam.
Vielleicht ein subtiles Mißverständnis/eine fehlende "No-Thread"-Anweisung, oder dgl.Ich bin wahrscheinlich nicht bewandert genug auf dem Gebiet, um dir wirklich zu helfen.
Also kann ich dir nur raten, es einmal auf comp.parallel oder comp.parallel.mpi zu
versuchen. Immerhin kann ich dir sagen, daß der C-Code unter deinen Voraussetzungen
stimmen sollte.
-
Hi Brandsim,
Du machst eine seltsame Sache, die auf lang oder kurz Probleme verursachen wird, wenn Du Dein jetziges überwunden hast:
fwrite(nxyz, 4,1,binfile); fwrite(nxyz+1,4,7,binfile);
Bist Du Dir ganz, ganz ganz sicher, daß Du wegschreibst, was Du wegschreiben wolltest?
Üblicherweise sieht das so aus:fwrite(&objekt, sizeof(objekt), objektzahl, outfile);
Mehr dazu in http://www.cplusplus.com/reference/clibrary/cstdio/fwrite.html. Auf jeden Fall ganz böse, den zweiten Parameter hart hineinzuschreiben.
, solltest Du ausbessern, daß Dir der Compiler das über sizeof() liefert!