Pregunta

Necesito un poco de ayuda con esto, ya que me sorprende en mi programa en C

Tengo 2 cadenas(base, y la ruta de acceso)

BASE: /home/steve/cps730
PATH: /page2.html

esta es la forma printf lee, a continuación, justo antes de que me llame un sprintf para unirse a su contenido.aquí está el bloque de código

        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);

Ahora, ¿puede usted explicar cómo el final de la instrucción printf devuelve

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

porque no entiendo en absoluto.

** He añadido 9000 en el malloc instrucción para evitar que el programa se bloquea (ya que el tamaño de la cadena es obviamente más grande que el 31 de bytes.

Salida Completa

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

EDITAR...................Todo el código que utiliza estas variables

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;
}
¿Fue útil?

Solución

Llama a readPage con un puntero no válido path: apunta a la memoria previamente asignada con el puntero method, que se libera justo antes de la llamada a malloc. El siguiente <=> puede reutilizar esta memoria y luego puede pasar cualquier cosa ...

Otros consejos

Bueno, claramente esto no puede suceder :-)

Supongo que su montón ya está horriblemente dañado.

Me gustaría ver los valores de puntero reales utilizados por filepath, input y base. Me pregunto si encontrará que la entrada está muy cerca de filepath?

También vería cómo se crearon originalmente la ruta de archivo, la base, etc., ¿podría tener un buffer desbordado allí?

Pruebe este código:

#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;
}

Si esto no tiene un problema, entonces debe haber algo mal en otra parte del código. Así es como el comportamiento indefinido a veces puede manifestarse (desordenar cómo funciona el código no relacionado).

(Por cierto, no agregué +1 a ambas llamadas eliminadas, ya que la cadena concatenada seguirá teniendo solo un terminador nulo).

Desde el BASE_DIR el valor se repite, ya sea BASE_DIR o filepath es, probablemente, la superposición de la en input memoria.

Asegúrese de que ambos BASE_DIR y filepath realmente ha asignado la memoria.

Un primer intento es hacer una copia local de BASE_DIR y filepath antes de llamar sprintf.

Aaah - la emoción de la persecución como la pregunta se transforma mientras estamos tratando de resolver el problema!

El código actual se parece a:

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);
    }
    ...

Pregunta:si este se está ejecutando en un servidor web, ¿es seguro usar el hilo inseguros función strtok()?Voy a asumir que "Sí, es seguro', aunque no estoy totalmente convencido.Tiene impresa la header cadena?Tiene impreso el valor de path?¿Realmente vas a dejar escapar el asignado path?¿Te das cuenta de que la malloc() + strcpy() la secuencia no copia BASE_DIR en path?


La versión original del código terminó con:

 printf("\n\nPATH: %s\n\n", filepath);

Por lo tanto la original sugirió respuesta parcial:

El formato en input;imprimir desde filepath?


¿Cuál es la probabilidad de que filepath puntos a los que ya han sido liberados de la memoria?Cuando se trata de asignar la memoria, usted podría conseguir cualquier cosa que esté pasando a la cuasi-aleatoria de la zona que filepath utilizado para apuntar.Otra posibilidad podría ser que filepath es un puntero a una variable local en una función que se ha devuelto - por lo que apunta a un lugar al azar en la pila que está siendo reutilizada por otros códigos, tales como sprintf().

También mencioné en un comentario que usted podría necesitar para asegurarse de que malloc() se declara y comprobar el valor devuelto de la misma.El '(char *)"reparto no es obligatorio en C (en C++), y muchos prefieren no incluir el reparto si el código es estrictamente C y no bilingües en C y C++.


Este código me funciona:

#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);
}

Se produce extrañas líneas vacías plus:

Alloc: 31
BASE: /home/steve/cps730
PATH: /page2.html
PATH: /page2.html
PATH: /home/steve/cps730/page2.html

La forma más fácil de averiguar qué está pasando es rastrear la ejecución en un depurador (posiblemente cayendo para rastrear el código de ensamblaje).

Algunas conjeturas sobre lo que podría estar pasando:

  • corrupción de memoria por otro hilo (parece poco probable si esto es fácilmente repetible)
  • montón corrupto (también parece poco probable, ya que vuelca las cadenas de 2 componentes después de la malloc() llamada)
  • como lo mencionó Jonathan Leffler en un comentario, es posible que le falte un encabezado (tal vez stdio.h) y el compilador está generando la secuencia incorrecta de llamadas / limpieza de pila para las llamadas printf / sprintf. Esperaría que vea algunas advertencias de tiempo de compilación si este fuera el caso, de las que debe tener en cuenta.

¿Qué compilador / destino estás usando?

Para hacer esto correctamente, cambiaría el código a:

/* 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;
}

Sugerencias


No hay nada obviamente malo con el programa. ( Actualización: bueno, ahora hay algo obvio. Durante la primera hora solo se publicaron unas pocas líneas y no tenían errores graves. ) Tendrás que publicar más. Aquí hay algunas ideas:

  1. malloc(3) devuelve void * por lo que no debería ser necesario lanzarlo. Si recibe una advertencia, lo más probable es que no haya incluido <stdlib.h>. Si no lo eres, deberías. (Por ejemplo, en un sistema de 64 bits, no crear prototipos gcc puede ser bastante serio. Algunos de los entornos de 64 bits realmente no admiten K & Amp; R C. :-)
  2. Hablando de advertencias, asegúrese de encenderlas todas. Con -Wall puede activar la mayoría de ellos con <=>.
  3. No está verificando el valor de retorno de <=> por un error.
  4. Use un depurador de memoria como Cerca eléctrica . Hay muchas opciones, mira mi enlace.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top