printf (), кажется, уничтожает мои данные - PullRequest
3 голосов
/ 08 июля 2011

Я пишу модуль nginx на C и получаю некоторые странные результаты.Я извлек функцию из моего модуля для проверки ее вывода, а также соответствующих определений типа / макроса 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 ]

7 голосов
/ 08 июля 2011

Эта строка является проблемой:

ngx_str_set(&h->key, str);

Здесь str является локальной переменной, и вы помещаете указатель на нее внутри h->key, которая будет возвращена вызывающей стороне.После возврата build_key_hash_pair указатель больше не будет действительным.Когда вы не вызывали никакую другую функцию, указатель все еще указывал на то же значение, но на это нельзя полагаться.Вызов printf переписал эту часть стека.

Вам нужно либо динамически распределить строку с помощью malloc или strdup, либо поместить массив внутри структуры key_hash_pair для храненияключ (возможно, если ключ всегда одного размера).

2 голосов
/ 08 июля 2011

build_key_hash_pair использует основанный на стеке массив str для заполнения поля data в ключе h. Когда вы выходите из функции, этот указатель больше не действителен, так как str выходит из области видимости.

Ваши результаты могут быть любыми: от правильной работы до сбоя программы. printf в функции будет работать, но определенно не при последующем вызове. ngx_str_set необходимо выделить память и скопировать в нее строку text (чтобы ее можно было позже освободить).

Я бы лично заменил все эти макросы на функции или встроенный код.

0 голосов
/ 08 июля 2011

Проблема в функции build_key_hash_pair, в частности, с переменной стека char str[56];, которая назначается на key_hash_pair с помощью макроса ngx_str_set.

Поскольку кадр стека, содержащий char str[56];, исчезает при возврате функции, все ставки на значение данных пары отключаются после завершения функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...