Ошибка памяти в C, когда данные перезаписываются - PullRequest
0 голосов
/ 20 февраля 2011

У меня есть следующая программа:

// required include statements...

static char ***out;

char* get_parameter(char* key)
{
    char *querystr = /*getenv("QUERY_STRING")*/ "abcdefg=abcdefghi";
    if (querystr == NULL)
        return (void*)0;

    char s[strlen(querystr)] ;
    strcpy(s, querystr);
    const char delim = '&';
    const char delim2 = '=';
    static size_t size = 0;
    if (out == 0)
    {
        out = (char*) malloc(sizeof(char*));
        size = split(s, &delim, out);
    }

    int i=0;
    for (; i<size; i++)
    {
        if ((*out)[i] != NULL)
        {
            char ***iout = NULL;
            iout = (char*) malloc(sizeof(char*));
            int isize = split((*out)[i], &delim2, iout);

            if (isize > 1 && ((*iout)[1]) != NULL && strcmp(key, (*iout)[0]) == 0)
            {
                size_t _size = strlen((*iout)[1]);
                char* value = (char*) malloc(_size*sizeof(char));
                strcpy(value, (*iout)[1]);
                free(iout);
                return value;
            }
        }
    }
    return (void*) 0;
}

static size_t count(const char *str, char ch)
{
    if (str == NULL) return 0;
    size_t count = 1;
    while (*str)
        if (*str++ == ch) count++;
    return count;
}

size_t split(const char *const str, const char* delim, char ***out)
{
    size_t size = count(str, *delim);
    *out = calloc(size, sizeof(char));
    char* token = NULL;
    char* tmp = (char*) str;
    int i=0;
    while ((token = strtok(tmp, delim)) != NULL)
    {
        tmp = NULL;
        (*out)[i] = (char*) malloc(sizeof strlen(token));
        strcpy((*out)[i++], token);
    }
    return size;
}

main()
{
    char* val = get_parameter("abcdefg");
    printf("%s\n", val);  // it should prints `abcdefghi`, but it prints `abcd?`
    free(val);
}

, как указано в основном методе, функция get_parameter должна печатать abcdefghi, но она печатает abcd?, где ? - символ управления сзначение 17.

Почему сброс строки не печатается?Я думаю, что неправильно использовал malloc для выделения соответствующего пространства.

Кроме того, есть ли какой-либо инструмент, который я могу использовать, чтобы узнать внутреннее представление памяти для моих указателей?

Ответы [ 3 ]

4 голосов
/ 20 февраля 2011

Вы имеете дело с C-Strings здесь. Вы должны рассмотреть 1 дополнительный байт для NULL-завершения ('\ 0')

Следовательно:

char s[strlen(querystr)] ;
strcpy(s, querystr);

неверно.

strlen вернет 4 для строки "abcd", но вам нужно выделить место для "abcd \ 0"

Так что вам нужно strlen + 1

0 голосов
/ 10 сентября 2011

Вы должны использовать gdb для пошагового запуска вашего бинарного файла и посмотреть, что не так. Valgrind - очень хороший инструмент, он подскажет, какая строка перезаписана в памяти и т. Д.

0 голосов
/ 20 февраля 2011

Линии

out = (char*) malloc(sizeof(char*));

iout = (char*) malloc(sizeof(char*));

проблема.

sizeof() возвращает количество байтов, необходимое для хранения объекта данного типа, в данном случае размер указателя (до char). malloc() затем выделяет столько байтов (по-видимому, 4 байта в вашей архитектуре). Чтобы это исправить, вам нужно дать malloc желаемую длину строки вместо использования sizeof.

Дополнительно линия

char* value = (char*) malloc(_size*sizeof(char));

имеет совершенно ненужное использование sizeof(). sizeof(char) гарантируется стандартом 1.

...