1

I am using the following function

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;
}

Up until the line header->next = h, everything works as planned. However, after the line h = malloc(sizeof(struct net_header));, the variables pch and str for some reason turn to NULL (I set breakpoints to find this). After the line temp = malloc(sizeof(struct net_header));, header also turns to NULL. Clearly, I have some kind of memory management issue, but I can't seem to find what it is. The header argument is initialized like this immediately before I call the function

header = malloc(sizeof(struct net_header));

struct net_header is declared as

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

I ran Xcode's static analyzer, which found no issues. I also have no compiler warnings or errors. I am running this program on Mac OS X 10.9.

Why are my variables being nullified after I call malloc()?

Chris Loonam
  • 5,735
  • 6
  • 41
  • 63
  • Does *str turn to NULL or str itself? str is a copy of a pointer on the stack or in a register and should never be affected by a call to malloc even in case of some memory management issue. The same applies to pch. – Meixner Apr 14 '15 at 19:23
  • `header->next = h;` will be a problem if `header` is NULL. How sure are you that `header` is not NULL? – R Sahu Apr 14 '15 at 19:23
  • @Meixner prior to `malloc`, it contains a string (`"foo"`), but after the call it is `NULL`, so I would say `str` itself. – Chris Loonam Apr 14 '15 at 19:25
  • @RSahu When I set the breakpoint anywhere before the while-loop, `header` points to a valid object, and its `name` value is properly set. – Chris Loonam Apr 14 '15 at 19:25
  • I cannot reproduce your problem. How do you call `parse_headers()` and how parameters are defined? Is this the only thread of execution? – Anto Jurković Apr 14 '15 at 19:43
  • @AntoJurković I call `parse_headers()` from another function (not `main()`), and I only have one thread. `str` contains an HTTP response and `header` is an empty struct (I show how I declare it in the question). – Chris Loonam Apr 14 '15 at 19:46
  • Is it possible that HTTP response is just changed before you finish parsing? I used your code and fixed string for `str` and it was parsed without problem. – Anto Jurković Apr 14 '15 at 19:52
  • There is nowhere else I can think of that `str` would be modified, so I doubt it. – Chris Loonam Apr 14 '15 at 19:59
  • 1
    try assigning to h with any other function call than `malloc()`. If you get similar behaviour (variables change arbitrarily), you suffer from stack corruption. – mfro Apr 14 '15 at 20:29
  • @Chris Probably a dumb question: Did you debug optimized code? If yes, all reported values may be wrong since the debugger may be looking at the wrong places. However, your code has one issue: malloc() is not guaranteed to initializes the returned memory to 0x00, i.e. your pointers inside the struct may contain some garbage unless overwritten. – Meixner Apr 14 '15 at 21:06
  • @Meixner the code's not optimized, so I believe the values are correct. – Chris Loonam Apr 14 '15 at 21:56
  • @mfro I'm thinking this is that's the issue, and I'm trying to find where I went wrong to cause the corruption. – Chris Loonam Apr 14 '15 at 21:56

2 Answers2

0

if you need to keep strtok result you have to dup it, with for example 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;
}

you need to call free somewhere to free the memory

Ôrel
  • 7,044
  • 3
  • 27
  • 46
0

I tried to reproduce your error, running on Mac OS X 10.10, and there is no problem with your code, it works perfectly.

Your problem comes from another call to malloc() with a bad size like in this post and in this one, generally caused by passing a pointer's size instead of the real size of variable's type.

I cannot tell you where since I don't see your entire code running before this "bad call", and I couldn't ask in comments because I don't have enough rights.

Hope it helps.

Community
  • 1
  • 1
Misery
  • 495
  • 4
  • 17