Я использую следующую функцию

int parse_headers(char *str, struct net_header *header)
{
    char *pch;
    struct net_header *h, *temp;

    pch = strtok(str, "\n");
    header->name = pch;

    h = malloc(sizeof(struct net_header));
    header->next = h;
    while ((pch = strtok(NULL, "\n")) != NULL)
    {
        h->name = pch;

        temp = malloc(sizeof(struct net_header));
        h->next = temp;
        h = temp;
    }
    return N_SUCCESS;
}

Вплоть до строки header->next = h все работает по плану. Однако после строки h = malloc(sizeof(struct net_header)); переменные pch и str почему-то превращаются в NULL (чтобы найти это, я поставил точки останова). После строки temp = malloc(sizeof(struct net_header)); header также превращается в NULL. Очевидно, у меня есть какая-то проблема с управлением памятью, но я не могу найти, что это такое. Аргумент header инициализируется таким образом непосредственно перед вызовом функции

header = malloc(sizeof(struct net_header));

struct net_header объявлен как

struct net_header
{
    char *name;
    char *content;
    struct net_header *next;
};

Я запустил статический анализатор Xcode, который не обнаружил проблем. У меня также нет предупреждений или ошибок компилятора. Я запускаю эту программу на Mac OS X 10.9.

Почему мои переменные обнуляются после вызова malloc()?

1
Chris Loonam 14 Апр 2015 в 22:08
*str превращается в NULL или в саму строку? str является копией указателя в стеке или в регистре, и на нее никогда не должен влиять вызов malloc, даже в случае какой-либо проблемы с управлением памятью. То же самое относится и к пч.
 – 
Meixner
14 Апр 2015 в 22:23
header->next = h; будет проблемой, если header равно NULL. Насколько вы уверены, что header не равно NULL?
 – 
R Sahu
14 Апр 2015 в 22:23
До malloc он содержит строку ("foo"), но после вызова это NULL, так что я бы сказал сам str.
 – 
Chris Loonam
14 Апр 2015 в 22:25
Когда я устанавливаю точку останова в любом месте перед циклом while, header указывает на допустимый объект, и его значение name установлено правильно.
 – 
Chris Loonam
14 Апр 2015 в 22:25
1
Попробуйте назначить h любым другим вызовом функции, кроме malloc(). Если вы получаете подобное поведение (переменные изменяются произвольно), вы страдаете от повреждения стека.
 – 
mfro
14 Апр 2015 в 23:29

2 ответа

Если вам нужно сохранить результат strtok, вы должны его дублировать, например, strdup

int parse_headers(char *str, struct net_header *header)
{
    char *pch;
    struct net_header *h, *temp;

    pch = strtok(str, "\n");
    header->name = strdup(pch);

    h = malloc(sizeof(struct net_header));
    header->next = h;
    while ((pch = strtok(NULL, "\n")) != NULL)
    {
        h->name = strdup(pch);

        temp = malloc(sizeof(struct net_header));
        h->next = temp;
        h = temp;
    }
    return N_SUCCESS;
}

Вам нужно позвонить free где-нибудь, чтобы освободить память

0
Ôrel 14 Апр 2015 в 22:30
Дополнительную информацию см. здесь: stackoverflow.com/questions/7100214/strtok-segfault
 – 
Tim
14 Апр 2015 в 22:34
1
Это полезно, но у меня все еще есть проблема с обнулением.
 – 
Chris Loonam
14 Апр 2015 в 22:35
Это только в том случае, если str может быть изменен, и вы хотите, чтобы header->name не зависел от str. Пока это не имеет никакого отношения к его проблеме.
 – 
antiduh
14 Апр 2015 в 22:35

Я попытался воспроизвести вашу ошибку, работая на Mac OS X 10.10, и с вашим кодом проблем нет, он работает отлично.

Ваша проблема возникает из-за другого вызова malloc() с неправильным размером, как в этом сообщении и в этот, обычно вызванный передачей размера указателя вместо реального размера типа переменной.

Я не могу сказать вам, где, так как я не вижу весь ваш код, работающий до этого «плохого вызова», и я не мог спросить в комментариях, потому что у меня недостаточно прав.

Надеюсь, это поможет.

0
Community 23 Май 2017 в 14:43
Я посмотрю на это, когда вернусь домой, и дам вам знать, если я что-нибудь найду.
 – 
Chris Loonam
14 Апр 2015 в 23:24
Есть новости по вашей проблеме? Вам удается это исправить?
 – 
Misery
16 Апр 2015 в 09:26