printf()似乎在破坏我的数据

我在C编写一个nginx模块,并有一些超级离奇的结果。 我从我的模块中提取了一个函数来testing它的输出以及相关的nginxtypes/macros定义。

我在我的build_key_hash_pair函数中构build一个结构,然后在printf()的内容上执行printf() 。 当我printf内部printf的数据时, main的输出是有效的。 当我在内部函数中删除printfmain打印一个空string。 这是令人困惑的,因为在函数调用build_key_hash_pair我不对数据进行操作,除了显示它。 这里是代码:

 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct ngx_str_t { size_t len; char *data; } ngx_str_t; typedef uintptr_t ngx_uint_t; typedef struct key_hash_pair { ngx_uint_t hash; ngx_str_t key; } key_hash_pair; #define ngx_string(str) { sizeof(str) - 1, (char *) str } #define ngx_str_set(str, text) \ (str)->len = sizeof(text) - 1; (str)->data = (char *) text #define ngx_hash(key, c) ((ngx_uint_t) key * 31 + c) #define ngx_str_null(str) (str)->len = 0; (str)->data = NULL void build_key_hash_pair(key_hash_pair *h, ngx_str_t api_key, ngx_str_t ip); int main (int argc, char const *argv[]) { ngx_str_t api_key = ngx_string("86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"); ngx_str_t ip = ngx_string("123.123.123.123"); key_hash_pair *pair; pair = malloc(sizeof(key_hash_pair)); build_key_hash_pair(pair, api_key, ip); printf("api_key = %s\n", api_key.data); printf("ip = %s\n", ip.data); printf("pair->key = %s\n", pair->key.data); printf("pair->hash = %u\n", (unsigned int)pair->hash); return 0; } void build_key_hash_pair(key_hash_pair *h, ngx_str_t api_key, ngx_str_t ip) { ngx_str_null(&h->key); char str[56]; memset(str, 0, sizeof(str)); strcat(str, api_key.data); strcat(str, ip.data); ngx_str_set(&h->key, str); ngx_uint_t i; for (i = 0; i < 56; i++) { h->hash = ngx_hash(&h->hash, h->key.data[i]); } } 

下面是我在build_key_hash_pair函数中执行printf("hello")时的输出:

 helloapi_key = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 ip = 123.123.123.123 pair->key = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8123.123.123.123 pair->hash = 32509824 

这里是(不寻常的)输出,当我不printf里面build_key_hash_pair

 api_key = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 ip = 123.123.123.123 pair->key = pair->hash = 32509824 

正如你所看到的, pair->key没有数据。 在gdb中,如果我在main中调用build_key_hash_pair之后立即断点, build_key_hash_pair pair->key包含适当的数据。 但是在第一次调用printf ,它是空白的。 内存地址保持不变,但数据刚刚消失。 谁能告诉我,我在做什么错了?

这条线是一个问题:

 ngx_str_set(&h->key, str); 

这里的str是一个局部变量,你在h->key里面放一个指针,这个指针会返回给调用者。 build_key_hash_pair返回后,指针将不再有效。 当你没有调用任何其他函数时,指针碰巧仍然指向相同的值,但这不是你可以依赖的。 printf的调用覆盖了堆栈的一部分。

你需要的是用mallocstrdup动态分配字符串,或者在key_hash_pair结构中放置一个数组来保存键值(如果键值总是相同的话)。

build_key_hash_pair使用基于堆栈的数组str来填充h键中的data字段。 从函数中退出时,由于str超出范围,该指针不再有效。

你的结果可能是从明显正确的操作到程序故障。 在printf中的printf将起作用,但如果事后调用,则肯定不会。 ngx_str_set需要分配内存并复制text字符串(当然后来释放)。

我会用函数或内联代码来替换所有这些宏。

问题出在build_key_hash_pair函数中,具体来说就是堆栈变量char str[56]; 通过宏ngx_str_set分配给key_hash_pair

由于堆栈框架包含char str[56]; 函数返回时消失,一旦函数结束,所有的赌注都将关闭。