2016-02-25 4 views
1

У меня есть функция, которая берет URL-адрес и возвращает запрашиваемый тип файла, но я не могу понять, как я могу освободить и вернуть символ malloc'd.c return variable и free malloc'd memory

const char* lookup(const char* path){ 
    char* rawEnding; 
    char* ending = malloc(strlen(path)); 
    char* mime = malloc(strlen(path)); 

    rawEnding = strrchr(path, '.'); 
    if(strcasecmp(rawEnding, ".css") == 0 || strcasecmp(rawEnding, ".html") == 0 || strcasecmp(rawEnding, ".javascript") == 0 || strcasecmp(rawEnding, ".php") == 0) { 
     memmove(ending, rawEnding+1, strlen(rawEnding)); 
     sprintf(mime, "text/%s", ending); 
     free(ending); 
     return mime; 
    } else if (strcasecmp(rawEnding, ".gif") == 0 || strcasecmp(rawEnding, ".ico") == 0 || strcasecmp(rawEnding, ".png") == 0) { 
     memmove(ending, ending+1, strlen(ending)); 
     sprintf(mime, "image/%s", ending); 
     return mime; 
    } else if (strcasecmp(rawEnding, ".jpg") == 0 || strcasecmp(rawEnding, ".jpeg") == 0) { 
     return "text/jpeg"; 
    } else { 
     return NULL; 
    } 
} 
+1

Если вы хотите вернуть 'mime', вы должны освободить его из-за функции. – Rabbid76

+0

Вы не можете освобождать и возвращать что-то, потому что освобождение его уничтожает. Вы должны освободить его извне, и из-за этого вы должны вернуть только память 'malloc''d или' NULL'. – zneak

+0

Ваш код не будет работать, если 'strrchr' возвращает' NULL'. Вы также не выделяете достаточную память для возвращаемой строки. Например, если «путь» равен «x.gif», «mime» будет указывать на 5-символьный буфер, но ваш код попытается поместить 10 символов, включая завершающий «NUL», в эти 5 символов. –

ответ

3

Это плохая идея, если функция возвращает строку буквального в одном случае и указатель на динамически allcated памяти в другом случае. Ваша функция должна всегда возвращать динамически выделенную память или NULL. Таким образом, вы можете free память вне функции.

const char* lookup(const char* path) 
{ 
    char* rawEnding = strrchr(path, '.'); 
    if (rawEnding == NULL) 
     return NULL; 

    char* ending = rawEnding + 1; 
    if (strcasecmp(ending, "css") == 0 || 
     strcasecmp(ending, "html") == 0 || 
     strcasecmp(ending, "javascript") == 0 || 
     strcasecmp(ending, "php") == 0) 
    { 
     int len = strlen("text/"); 
     char* mime = malloc(len + strlen(ending) + 1); 
     strcpy(mime, "text/"); 
     strcpy(mime + len, ending); 
     return mime; 
    } 
    else if (strcasecmp(ending, "gif") == 0 || 
       strcasecmp(ending, "ico") == 0 || 
       strcasecmp(ending, "png") == 0) 
    { 
     int len = strlen("image/"); 
     char* mime = malloc(len + strlen(ending) + 1); 
     strcpy(mime, "image/"); 
     strcpy(mime + len, ending); 
     return mime; 
    } 
    else if (strcasecmp(ending, "jpg") == 0 || 
       strcasecmp(ending, "jpeg") == 0) 
    { 
     char* mime = malloc(strlen("text/jpeg") + 1); 
     strcpy(mime, "text/jpeg"); 
     return mime; 
    } 
    return NULL; 
} 
0

Я вижу, что если окончание «JPG» или «JPEG» конвертировать его «текст/JPEG». Это то, что вы имели в виду?

Вы не можете освободить mime, потому что хотите использовать его в вызывающей функции. После того, как вы закончите использовать его, вы сможете освободить его после первой проверки, что это не «text.jpg» или NULL.

В качестве альтернативы вы можете обрабатывать его одним возвратом. Затем снаружи вы можете освободить мим, если он не является NULL.

if(strcasecmp(rawEnding, ".css") == 0 || strcasecmp(rawEnding, ".html") == 0 || strcasecmp(rawEnding, ".javascript") == 0 || strcasecmp(rawEnding, ".php") == 0) { 
    memmove(ending, rawEnding+1, strlen(rawEnding)); 
    sprintf(mime, "text/%s", ending); 
    free(ending); 
    // return mime; 
} else if (strcasecmp(rawEnding, ".gif") == 0 || strcasecmp(rawEnding, ".ico") == 0 || strcasecmp(rawEnding, ".png") == 0) { 
    memmove(ending, ending+1, strlen(ending)); 
    sprintf(mime, "image/%s", ending); 
    // return mime; 
} else if (strcasecmp(rawEnding, ".jpg") == 0 || strcasecmp(rawEnding, ".jpeg") == 0) { 
    strcpy(mime, "text/jpeg"); 
} else { 
    free(mime); 
    mime = NULL; 
} 
return mime;