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

时间:2011-07-08 17:47:02

标签: c gdb nginx

我正在用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之后,它被删除了。内存地址保持不变,但数据刚刚消失。谁能告诉我世界上我做错了什么?

3 个答案:

答案 0 :(得分:7)

这一行是个问题:

ngx_str_set(&h->key, str);

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

您需要的是使用mallocstrdup动态分配字符串,或者在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];的堆栈帧在函数返回时消失,所以一旦函数结束,所有的投注都将关闭该对数据的值。