gpt4 book ai didi

条件跳转或移动取决于 C 中未初始化的值

转载 作者:行者123 更新时间:2023-11-30 16:48:08 24 4
gpt4 key购买 nike

我有这个函数返回一个如下所示的 parsed_url 结构

typedef struct url_parser_url {
char *protocol;
char *host;
int port;
char *path;
char *query_string;
int host_exists;
} url_parser_url_t;

url_parser_url_t *parsed_url;
parsed_url = (url_parser_url_t *) malloc(sizeof(url_parser_url_t));
parse_url(address, true, parsed_url);
printf("parsed_url->path = %s\n", parsed_url->path);

parse_url 函数看起来像

int parse_url(char *url, bool verify_host, url_parser_url_t *parsed_url) {
char *local_url = (char *) malloc(sizeof(char) * (strlen(url) + 1));
char *token;
char *token_host;
char *host_port;
char *token_ptr;
char *host_token_ptr;

char *path = NULL;
strcpy(local_url, url);

token = strtok_r(local_url, ":", &token_ptr);
parsed_url->protocol = (char *) malloc(sizeof(char) * strlen(token) + 1);
strcpy(parsed_url->protocol, token);

token = strtok_r(NULL, "/", &token_ptr);
if (token) {
host_port = (char *) malloc(sizeof(char) * (strlen(token) + 1));
strcpy(host_port, token);
} else {
host_port = (char *) malloc(sizeof(char) * 1);
strcpy(host_port, "");
}

token_host = strtok_r(host_port, ":", &host_token_ptr);
if (token_host) {
parsed_url->host = (char *) malloc(
sizeof(char) * strlen(token_host) + 1);
strcpy(parsed_url->host, token_host);

if (verify_host) {
struct hostent *host;
host = gethostbyname(parsed_url->host);
if (host != NULL) {
parsed_url->host_exists = 1;
} else {
parsed_url->host_exists = 0;
}
} else {
parsed_url->host_exists = -1;
}
} else {
parsed_url->host_exists = -1;
parsed_url->host = NULL;
}

token_host = strtok_r(NULL, ":", &host_token_ptr);
if (token_host)
parsed_url->port = atoi(token_host);
else
parsed_url->port = 0;

token_host = strtok_r(NULL, ":", &host_token_ptr);
assert(token_host == NULL);

token = strtok_r(NULL, "?", &token_ptr);
parsed_url->path = NULL;
if (token) {
path = (char *) realloc(path, sizeof(char) * (strlen(token) + 2));
strcpy(path, "/");
strcat(path, token);
parsed_url->path = (char *) malloc(sizeof(char) * strlen(path) + 1);
strncpy(parsed_url->path, path, strlen(path));
free(path);
} else {
parsed_url->path = (char *) malloc(sizeof(char) * 2);
strcpy(parsed_url->path, "/");
}

token = strtok_r(NULL, "?", &token_ptr);
if (token) {
parsed_url->query_string = (char *) malloc(
sizeof(char) * (strlen(token) + 1));
strncpy(parsed_url->query_string, token, strlen(token));
} else {
parsed_url->query_string = NULL;
}

token = strtok_r(NULL, "?", &token_ptr);
assert(token == NULL);

free(local_url);
free(host_port);
return 0;
}

问题是当我调用函数 parse_url 然后使用 parsed_url->path 成员时,它会抛出这个段错误

==16647== Conditional jump or move depends on uninitialised value(s)

任何人都可以向我解释发生了什么以及为什么吗?谢谢

最佳答案

就是这样。尽管它被认为是 strcpy() 的更安全替代方案,但 strncpy() 有一个令人讨厌的缺点。标准规定:

The strncpy function copies not more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 to the array pointed to by s1.

( C2011 7.24.2.4/2 ),注释 308 澄清了这一点

Thus, if there is no null character in the first n characters of the array pointed to by s2, the result will not be null-terminated.

最终对您的特定 valgrind 投诉负责的代码是:

    strncpy(parsed_url->path, path, strlen(path));

由于根据定义,path 的第一个 strlen(path) 字符中不能有空字符,因此 strncpy() 确实会失败以确保副本以空终止。您的代码中至少存在同一问题的另一个实例。

由于您似乎非常小心地确保有足够的可用空间,因此一种解决方案是从 strncpy() 切换到 strcpy()。这也会更高效,因为您可以避免重复调用 strlen()

正如我在评论中指出的,但是,如果您愿意依赖 POSIX 的 strdup(),那么它比 strlen() + malloc 更干净() + str[n]cpy(),并且具有相同的语义(您负责释放为副本分配的内存)。如果您以这种方式制作副本,您甚至没有机会犯这些错误。

关于条件跳转或移动取决于 C 中未初始化的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43079929/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com