strtok和内存泄漏

gui*_*ouz 5 c memory malloc free strtok

我使用strtok()编写了一个简单的url解析器.这是代码

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char *protocol;
    char *host;
    int port;
    char *path;
} aUrl;


void parse_url(char *url, aUrl *ret) {

    printf("Parsing %s\n", url);
    char *tmp = (char *)_strdup(url);
    //char *protocol, *host, *port, *path;
    int len = 0;

    // protocol agora eh por exemplo http: ou https:
    ret->protocol = (char *) strtok(tmp, "/");
    len = strlen(ret->protocol) + 2;

    ret->host = (char *) strtok(NULL, "/");


    len += strlen(ret->host);

    //printf("char at %d => %c", len, url[len]);

    ret->path = (char *)_strdup(&url[len]);

    ret->path = (char *) strtok(ret->path, "#");

    ret->protocol = (char *) strtok(ret->protocol, ":");

    // host agora é por exemplo address.com:8080
    //tmp = (char *)_strdup(host);
    //strtok(tmp, ":");
    ret->host = (char *) strtok(ret->host, ":");
    tmp = (char *) strtok(NULL, ":");

    if(tmp == NULL) {
        if(strcmp(ret->protocol, "http") == 0) {
            ret->port = 80;
        } else if(strcmp(ret->protocol, "https") == 0) {
            ret->port = 443;
        }
    } else {
        ret->port = atoi(tmp);
    }


    //host = (char *) strtok(NULL, "/");




}

/*
 * 
 */
int main(int argc, char** argv) {
    printf("hello moto\n");

    aUrl myUrl;
    parse_url("http://teste.com/Teste/asdf#coisa", &myUrl);


    printf("protocol is %s\nhost is %s\nport is %d\npath is %s\n", myUrl.protocol, myUrl.host, myUrl.port, myUrl.path);

    return (EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我使用strtok()很多,所以我可以"切片"网址.我不需要支持不同于http或https的网址,因此它完成的方式解决了我的所有问题.我担心的是(这是在嵌入式设备上运行) - 我是在浪费内存吗?当我写的东西像

ret->protocol = (char *) strtok(tmp, "/");
Run Code Online (Sandbox Code Playgroud)

然后打电话

ret->protocol = (char *) strtok(ret->protocol, ":");
Run Code Online (Sandbox Code Playgroud)

我首先将指针ret->协议保留在内存中吗?我想也许我应该设置第一次调用tmp指针,调用strtok指向ret-> protocol到字符串的右边部分(第二次调用)然后free(tmp).

什么应该是使用strtok的最佳方式?

Ben*_*tto 22

要直接回答你的问题,strtok只返回一个指向你给它作为输入的字符串内部位置的指针 - 它没有为你分配新的内存,所以不需要在它给你的任何指针上调用free回来了.

对于它的价值,您还可以查看"strchr"和"strstr",它们是在字符串中搜索单个字符或序列的非破坏性方式.

另请注意,此处的内存分配存在问题 - 您使用strdup()在解析函数中分配新字符串,然后将该内存块的片段分配给"ret"字段.因此,你的调用者将负责释放strdup的字符串,但由于你只是在ret中隐式地传回该字符串,调用者需要神奇地知道要传递给free的指针.(可能是ret-> protocol,但可能不是,具体取决于输入的外观.)


Whi*_*ght 5

strtok修改了字符串,用NULL替换指定的字符.由于C中的字符串以NULL结尾,现在看来您的原始指针指向较短的字符串,即使原始字符串仍然存在并且仍然占用相同数量的内存(但字符替换为NULL).我认为,字符串的结尾包含一个双NULL.

简短的回答是:保持指向字符串缓冲区开头的指针,并在解析时指向另一个指向字符串的"当前"指针.当您使用strtok或以其他方式迭代字符串时,您更新"当前"指针但保留单独的开始指针.当你完成后,free()开始指针.没有记忆泄露.