我正在用C编写一个nginx模块,并且有一些非常奇怪的结果。我从我的模块中提取了一个函数来测试它的输出以及相关的nginx类型/宏定义。
我正在我的build_key_hash_pair
函数中构建一个结构,然后对printf()
中的内容执行main
。当我printf
内部函数内的数据时,main
的输出是有效的。当我删除内部函数中的printf
时,main
会打印一个空字符串。这很令人困惑,因为在调用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]);
}
}
以下是我在printf("hello")
函数中执行build_key_hash_pair
时的输出:
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
的调用之后立即断点,pair->key
包含适当的数据。但是在第一次调用printf
之后,它被删除了。内存地址保持不变,但数据刚刚消失。谁能告诉我世界上我做错了什么?
答案 0 :(得分:7)
这一行是个问题:
ngx_str_set(&h->key, str);
这里str
是一个局部变量,你在h->key
内放置一个指向它的指针,它将被返回给调用者。在build_key_hash_pair
返回后,指针将不再有效。当你没有调用任何其他函数时,指针仍然指向相同的值,但这不是你可以依赖的东西。对printf
的调用覆盖了堆栈的那一部分。
您需要的是使用malloc
或strdup
动态分配字符串,或者在key_hash_pair
结构中放置一个数组来保存密钥(如果密钥始终是相同的尺寸)。
答案 1 :(得分:2)
build_key_hash_pair
使用基于堆栈的数组str
填充data
键中的h
字段。退出函数时,该指针不再有效,因为str
超出范围。
您的结果可能是从明显正确的操作到程序失败。函数中的printf
将起作用,但如果事后调用则绝对不行。 ngx_str_set
需要分配内存并将text
字符串复制到其中(当然可以在以后释放)。
我会亲自用函数或内联代码替换所有这些宏。
答案 2 :(得分:0)
问题出在build_key_hash_pair
函数中,特别是堆栈变量char str[56];
,它通过宏key_hash_pair
分配给ngx_str_set
。
由于包含char str[56];
的堆栈帧在函数返回时消失,所以一旦函数结束,所有的投注都将关闭该对数据的值。