Frage
Ich brauche Hilfe bei dieser, da es mir in meinem C-Programm Leitbleche
Ich habe 2 Strings (Basis, und Pfad)
BASE: /home/steve/cps730
PATH: /page2.html
Dies ist, wie printf liest dann, kurz bevor ich einen sprintf nennen ihre Inhalte miteinander zu verbinden. hier ist der Codeblock
int memory_alloc = strlen(filepath)+1;
memory_alloc += strlen(BASE_DIR)+1;
printf("\n\nAlloc: %d",memory_alloc);
char *input = (char*)malloc(memory_alloc+9000);
printf("\n\nBASE: %s\nPATH: %s\n\n",BASE_DIR,filepath);
sprintf(input, "%s%s",BASE_DIR,filepath); // :(
printf("\n\nPATH: %s\n\n",input);
Sie können nun erklären, wie die letzte printf Anweisung gibt
PATH: e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/stev
, weil sie nicht verstehen überhaupt.
** Ich habe 9000 in der malloc Erklärung Programm, um zu verhindern (da die Größe der Zeichenfolge Absturz ist offensichtlich größer als 31 Bytes.
Voll Ausgabe
Alloc: 31
BASE: /home/steve/cps730
PATH: /page2.html
PATH: /home/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/steve/cps730e/stev
Sending:
HTTP/1.0 404 Not Found
Date: Sat, 12 Sep 2009 19:01:53 GMT
Connection: close
EDIT ................... der gesamte Code, der diese Variablen verwendet
const char *BASE_DIR = "/home/steve/cps730";
char* handleHeader(char *header){
//Method given by browser (will only take GET, POST, and HEAD)
char *method;
method = (char*)malloc(strlen(header)+1);
strcpy(method,header);
method = strtok(method," ");
if(!strcmp(method,"GET")){
char *path = strtok(NULL," ");
if(!strcmp(path,"/")){
path = (char*)malloc(strlen(BASE_DIR)+1+12);
strcpy(path,"/index.html");
}
free(method);
return readPage(path);
}
else if(!strcmp(method,"POST")){
}
else if(!strcmp(method,"HEAD")){
}
else{
strcat(contents,"HTTP/1.1 501 Not Implemented\n");
strcat(contents, "Date: Sat, 12 Sep 2009 19:01:53 GMT\n");
strcat(contents, "Connection: close\n\n");
}
free(method);
}
//Return the contents of an HTML file
char* readPage(char* filepath){
int memory_alloc = strlen(filepath)+1;
memory_alloc += strlen(BASE_DIR)+1;
printf("\n\nAlloc: %d",memory_alloc);
char *input = (char*)malloc(memory_alloc+9000);
printf("\n\nBASE: %s\nPATH: %s\n\n",BASE_DIR,filepath);
sprintf(input, "%s%s\0",BASE_DIR,filepath);
printf("\n\nPATH: %s\n\n",input);
FILE *file;
file = fopen(input, "r");
char temp[255];
strcat(contents,"");
if(file){
strcat(contents, "HTTP/1.1 200 OK\n");
strcat(contents, "Date: Sat, 12 Sep 2009 19:01:53 GMT\n");
strcat(contents, "Content-Type: text/html; charset=utf-8\n");
strcat(contents, "Connection: close\n\n");
//Read the requested file line by line
while(fgets(temp, 255, file)!=NULL) {
strcat(contents, temp);
}
}
else{
strcat(contents, "HTTP/1.0 404 Not Found\n");
strcat(contents, "Date: Sat, 12 Sep 2009 19:01:53 GMT\n");
strcat(contents, "Connection: close\n\n");
}
return contents;
}
Lösung
Sie rufen readPage
mit einer ungültigen Zeiger path
- er zeigt in die Speicher zuvor mit dem method
Zeiger zugeordnet, der direkt befreit wird, bevor der Anruf an readPage
. Der nächste malloc
kann diesen Speicher wieder verwenden und dann kann alles passieren ...
Andere Tipps
Nun, klar kann dies nicht passieren: -)
Meine Vermutung ist, dass Ihr Haufen schrecklich bereits beschädigt ist.
würde ich auf dem tatsächlichen Zeigerwert von filepath, Eingabe- und Base suchen. Ich frage mich, wenn Sie, dass die Eingabe ganz in der Nähe zu finden, ist zu dateipfad?
würde ich auch an, wie filepath, Base etc ursprünglich erstellt wurden, können Sie einen Puffer Überlauf haben da?
Versuchen Sie diesen Code ein:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char* BASE_DIR = "/home/steve/cps730";
const char* filepath = "/page2.html";
int memory_alloc = strlen(filepath);
memory_alloc += strlen(BASE_DIR)+1;
printf("\n\nAlloc: %d",memory_alloc);
char *input = (char*)malloc(memory_alloc);
printf("\n\nBASE: %s\nPATH: %s\n\n",BASE_DIR,filepath);
sprintf(input, "%s%s",BASE_DIR,filepath); // :(
printf("\n\nPATH: %s\n\n",input);
return 0;
}
Wenn dies kein Problem hat, dann muss es etwas falsch an anderer Stelle im Code. Das ist, wie nicht definiertes Verhalten manchmal manifestieren sich (vermasselt, wie in keinem Zusammenhang Code funktioniert).
(BTW, ich habe +1 nicht auf beiden Strlen Anrufe, da die verkettete Zeichenfolge noch wird nur ein Null-Terminator haben.)
Da der BASE_DIR
Wert wiederholt sich, entweder BASE_DIR
oder filepath
wahrscheinlich überlappt die in input
Speicher.
Stellen Sie sicher, beide BASE_DIR
und filepath
wirklich zugewiesenen Speicher hat.
Ein erster Versuch ist nur eine lokale Kopie BASE_DIR
und filepath
macht vor sprintf
aufrufen.
Aaah - der Nervenkitzel der Jagd wie die Frage, Morphs, während wir versuchen, das Problem zu lösen
Der aktuelle Code wie folgt aussieht:
const char *BASE_DIR = "/home/steve/cps730";
//Handles the header sent by the browser
char* handleHeader(char *header){
//Method given by browser (will only take GET, POST, and HEAD)
char *method;
method = (char*)malloc(strlen(header)+1);
strcpy(method,header);
method = strtok(method," ");
if(!strcmp(method,"GET")){
char *path = strtok(NULL," ");
if(!strcmp(path,"/")){
path = (char*)malloc(strlen(BASE_DIR)+1+12);
strcpy(path,"/index.html");
}
free(method);
return readPage(path);
}
...
Frage: wenn dies in einem Web-Server ausgeführt wird, ist es sicher, die gewinde unsichere Funktion strtok()
zu verwenden? Ich werde ‚Ja, es ist sicher‘ zu übernehmen, obwohl ich nicht ganz überzeugt bin. Haben Sie die header
Zeichenfolge gedruckt? Haben Sie den Wert path
gedruckt? Haben Sie wirklich die Absicht, die zugewiesene path
undicht? Wissen Sie, dass die malloc() + strcpy()
Sequenz nicht BASE_DIR
in path
kopiert?
Die ursprüngliche Version des Codes endete mit:
printf("\n\nPATH: %s\n\n", filepath);
Damit die ursprüngliche vorgeschlagene Teilantwort:
Sie formatieren in
input
; Sie drucken ausfilepath
?
Was ist die Chance, dass filepath
Punkte bereits Speicher freigegeben? Wenn Sie den Speicher zuweisen, könnten Sie etwas passiert mit dem quasi-zufälligen Bereich bekommen, die filepath
verwendet zu zeigen. Eine andere Möglichkeit könnte sein, dass filepath
ist ein Zeiger auf eine lokale Variable in einer Funktion, die zurückgegeben hat -. So verweist er auf irgendwo zufällig in dem Stapel, die von anderen Code, wie sprintf()
wieder verwendet wird
ich auch in einem Kommentar erwähnt, die Sie möglicherweise benötigen könnten, dass malloc()
, um sicherzustellen, erklärt ist, und überprüfen Sie den Rückgabewert von ihm. Die Besetzung ‚(char *)
‘ ist nicht zwingend in C (es ist in C ++), und viele es vorziehen, nicht die Besetzung schließen, wenn der Code streng C und nicht zweisprachig in C und C ++.
Dieser Code funktioniert für mich:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *BASE_DIR = "/home/steve/cps730";
const char *filepath = "/page2.html";
int memory_alloc = strlen(filepath) + 1;
memory_alloc += strlen(BASE_DIR) + 1;
printf("\n\nAlloc: %d", memory_alloc);
char *input = (char*)malloc(memory_alloc + 9000);
printf("\n\nBASE: %s\nPATH: %s\n\n", BASE_DIR, filepath);
sprintf(input, "%s%s", BASE_DIR, filepath);
printf("\n\nPATH: %s\n\n", filepath);
printf("\n\nPATH: %s\n\n", input);
return(0);
}
Es produziert Fremd leere Linien plus:
Alloc: 31
BASE: /home/steve/cps730
PATH: /page2.html
PATH: /page2.html
PATH: /home/steve/cps730/page2.html
Der einfachste Weg, um herauszufinden, was los ist in einem Debugger durch die Ausführung zu verfolgen (möglicherweise Verfolgung des Assembler-Code fallen).
Ein paar Vermutungen darüber, was man vor sich gehen:
- Speicherbeschädigung durch einen anderen Thread (scheint unwahrscheinlich, wenn dies ohne weiteres wiederholbar ist)
- korrupte Haufen (auch unwahrscheinlich scheint, wie Sie die 2-Komponenten-Strings nach dem Aufruf
malloc()
Dump) - wie von Jonathan Leffler in einem Kommentar erwähnt, könnten Sie einen Header (vielleicht
stdio.h
) fehlt und der Compiler generiert die falsche calling / Stapelreihenfolge für dieprintf
/sprintf
Anrufe aufzuräumen. Ich würde erwarten, dass Sie einige der Kompilierung Warnungen sehen würde, wenn dies der Fall wäre -. Diejenigen, die Sie zur Kenntnis nehmen sollten
Welche Compiler / Ziel verwenden Sie?
dies richtig zu tun, würde ich den Code ändern:
/* CHANGED: allocate additional space for "index.html" */
method = (char*)malloc(strlen(header)+1+10);
strcpy(method,header);
method = strtok(method," ");
if(!strcmp(method,"GET")){
char *path = strtok(NULL," ");
if(!strcmp(path,"/")){
/* CHANGED: don't allocate new memory, use previously allocated */
strcpy(path,"/index.html");
}
/* CHANGED: call function first and free memory _after_ the call */
char *result = readPage(path);
free(method);
return result;
}
Vorschläge
Es gibt nichts, offensichtlich falsch mit dem Programm. ( Update:.. na ja, es ist etwas offensichtlich jetzt zum ersten Stunde nur ein paar Zeilen wurden geschrieben, und sie hatten keine ernsthafte Fehler ) Sie müssen mehr davon schreiben. Hier sind einige Ideen:
-
malloc(3)
kehrtvoid *
so ist es nicht notwendig sein sollte, es zu werfen. Wenn Sie eine Warnung erhalten, ist es sehr wahrscheinlich bedeutet, dass Sie nicht<stdlib.h>
enthalten waren. Wenn Sie nicht sind, sollten Sie. (Zum Beispiel auf einem 64-Bit-System nichtmalloc(3)
Prototyping kann sehr ernst sein Einige der 64-Bit-Umgebungen nicht wirklich unterstützen K & R C: -). - Warnungen Sprechen Sie bitte sicher, dass Sie sie alle auf drehen. Mit
gcc
können Sie die meisten von ihnen schalten Sie mit-Wall
. - Du bist gerade nicht den Rückgabewert von
malloc(3)
für einen Fehler. - einen Speicher-Debugger verwenden wie Electric Fence . Es gibt viele Möglichkeiten, sieht meine Verbindung.