我用strtok()写了一个简单的url解析器。 这是代码
#include #include typedef struct { char *protocol; char *host; int port; char *path; } aUrl; void parse_url(char *url, aUrl *ret) { printf("Parsing %sn", 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 moton"); aUrl myUrl; parse_url("https://teste.com/Teste/asdf#coisa", &myUrl); printf("protocol is %snhost is %snport is %dnpath is %sn", myUrl.protocol, myUrl.host, myUrl.port, myUrl.path); return (EXIT_SUCCESS); }
正如你所看到的,我使用strtok()很多,所以我可以“切片”url。 我不需要支持不同于http或https的url,所以它完成的方式解决了我的所有问题。 我担心的是(这是在嵌入式设备上运行) – 我是在浪费内存吗? 当我写的东西像
ret->protocol = (char *) strtok(tmp, "/");
然后打电话
ret->protocol = (char *) strtok(ret->protocol, ":");
我首先将指针ret->协议保留在内存中吗? 我想也许我应该设置第一次调用tmp指针,调用strtok指向ret-> protocol到字符串的右边部分(第二次调用)然后free(tmp)。
什么应该是使用strtok的最佳方式?
要直接回答你的问题,strtok只会返回一个指向你给它作为输入的字符串内部位置的指针 – 它不会为你分配新的内存,所以不需要在它给你的任何指针上调用free回来了。
对于它的价值,您还可以查看“strchr”和“strstr”,它们是在字符串中搜索单个字符或序列的非破坏性方式。
另请注意,此处的内存分配存在问题 – 您使用strdup()在解析函数中分配新字符串,然后将该内存块的片段分配给“ret”字段。 因此,你的调用者将负责释放strdup’d字符串,但由于你只是将这个字符串隐式地传回ret中,调用者需要神奇地知道要传递给free的指针。 (可能是ret-> protocol,但可能不是,取决于输入的外观。)
strtok修改了字符串,用NULL替换指定的字符。 由于C中的字符串以NULL结尾,现在看来您的原始指针指向较短的字符串,即使原始字符串仍然存在且仍占用相同数量的内存(但字符替换为NULL)。 我认为,字符串的结尾包含一个双NULL。
简短的回答是:保持指向字符串缓冲区开头的指针,并在解析时指向另一个指向字符串的“当前”指针。 当您使用strtok或以其他方式迭代字符串时,您更新“当前”指针但保留单独的开始指针。 当你完成后,free()开始指针。 没有记忆泄露。
你知道你可以继续使用NULL作为strtok的第一个参数来解析字符串吗?
第一个电话:
char* token = strtok(string, delimiters);
然后:
token = strtok(NULL, other_delimiters);
这样可以简化代码:
int parse_url(char *url, aUrl *ret) { //get protocol char* token = strtok(url, "/"); if( token == NULL ) return -1; strcpy(ret->protocol, token); strcat(ret->protocol, "//"); // skip next '/' token = strtok(NULL, "/"); if( token == NULL ) return -1; //get host token = strtok(NULL, "/"); if( token == NULL ) return -1; strcpy(ret->host, token); // get path token = strtok(NULL, "#"); if( token == NULL ) return -1; strcpy(ret->path, token); // ... return 0; }
你可以看到我有一个返回值来知道解析是否成功完成。
感谢您分享您的代码! 我在valgrind中运行它并修复了由strdup函数生成的两个内存泄漏。
需要了解更多c/c++开发分享strtok和内存泄漏,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!
#include #include #include typedef struct { char *protocol; char *host; int port; char *path; } URL; void parse_url(char *url, URL *ret) { char *tmp = (char *) strdup(url); int len = 0; ret->protocol = (char *) strtok(tmp, "/"); len = strlen(ret->protocol) + 2; ret->host = (char *) strtok(NULL, "/"); len += strlen(ret->host); ret->path = (char *) strdup(&url[len]); ret->path = (char *) strtok(ret->path, "#"); ret->protocol = (char *) strtok(ret->protocol, ":"); 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); } } void free_url(URL *url) { free(url->path); free(url->protocol); } int main(int argc, char** argv) { URL url; parse_url("https://example.com:3000/Teste/asdf#coisa", &url); printf("protocol: %snhost: %snport: %dnpath: %sn", url.protocol, url.host, url.port, url.path); free_url(&url); return (EXIT_SUCCESS); }
以上就是c/c++开发分享strtok和内存泄漏相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/979608.html