Thread: malloc does not seem to return

  1. #1
    Registered User
    Join Date
    Jul 2011
    Posts
    99

    malloc does not seem to return

    I have a function that walks through a message string. The message string has a begin indicator, and an END indicator en a Separator to separate the key=value pairs in the string. It should return a linked list to struct's that each contain a key value pairs so it can be processes elsewhere in the program.

    I will describe briefly what happens. If I call the function with a teststring, it processes a few key value pairs, then after processing two key value pairs it does not seem to return from the malloc call, that I have marked red and bold.

    I am aware that this may not be detailed enough, but I can post additional code/information if needed. Maybe one of the giants here spots the mistake in this code already.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "messaging.h"
    
    struct keyValuePair {
    	int key;
    	char *value;
    	struct keyValuePair *next;
    
    struct keyValuePair *parseMessageString(char *aMessageString) {
    
    	//set walker to the first position of the first key of the message
    	char *walker = aMessageString + strlen(BEGIN);
    	char *end = strstr(aMessageString, END); //this ptr is set at the end of the messg
    	char *sep; //
    
    	char *key = malloc(MAXFIELD * sizeof(*key + 1));
    	char *value;
    	int i = 0; //index for key and value pointers
    	int type;  //value for fieldtype
    
    	struct keyValuePair *firstPair = NULL;
    	struct keyValuePair *prevPair;
    	struct keyValuePair *currPair;
    
    	//walk through message string, convert keys into integer
    	//and store key and value in the linked list firstPair
    	while (walker != end) {
    
    		//get key digits untill you encounter '='
    		i = 0;
    		while ((*walker != '=')) {
    			key[i] = *walker;
    			++walker;
    			++i;
    		}
    		key[i] = '\0'; //key[] contains key now
    		type = atoi(key);
    printf("key= %i \n", type);
    	
    		//set sep to next separator or the end for next while loop
    		sep = ((strstr(walker, SEP) == NULL) ? end : strstr(walker, SEP));
    
    		//store the value
    		walker++; //was on the = sign
    		i = 0;
    		value = malloc(MAXFIELD * sizeof(*value + 1));
    		if (value == NULL) printf("\nMalloc issue\n");
    		while (walker != sep)
    			value[i++] = *(walker++);
    		value[i] = '\0';//value[] contains now the value
    printf("VAL value= %s\n", value);
    
    		currPair = malloc(sizeof(currPair));
    printf("namallod\n");
    		if (currPair == NULL) printf("\nMalloc Error\n");
    		currPair->key = type;
    		currPair->value = value;
    		currPair->next = NULL;
    
    
    printf("CURR key= %i value= %s\n", type, value);
    		//add cuurPair to the linked list
    		if (firstPair == NULL) {
    			firstPair = currPair;
    			prevPair = currPair;
    		}
    		else {
    			prevPair->next = currPair;
    			prevPair = currPair;
    		}
    		if (sep != end)
    			walker += strlen(SEP);
    	}	
    	return firstPair;
    }

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Code:
    value = malloc(MAXFIELD * sizeof(*value + 1));
    I am not sure what this line does! I would guess it is not what you want it to do.

    Tim S.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    I've only looked at your malloc() calls. All are broken, so I have not looked further.

    I'll recreate each line here, with a comment showing what each is ACTUALLY equivalent to. Check and see if you are doing what you expect.

    Code:
          char *key = malloc(MAXFIELD * sizeof(*key + 1));       /*   char *key = malloc(MAXFIELD * sizeof(int))   */
    
         value = malloc(MAXFIELD * sizeof(*value + 1));           /*    value = malloc(MAXFIELD * sizeof(int))  */
    
         currPair = malloc(sizeof(currPair));                             /*   currPair = malloc(sizeof(struct KeyValuePair *))   */
    The net effect, in most cases, is likely to be that each malloc() call is allocating less memory than you expect, so other code is merrily tromping memory beyond the end of what is actually malloc()'d. That corrupts some arbitrary area of memory that your program should not be writing to. If that memory is critical to the functioning of malloc(), that would explain why malloc() is not returning.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    I put this line in for the following reason.
    At first, I had value declared just as a char pointer. What then happened was,t hat the pointer firstPair, who is supposed to point at the first record, changed the value for firstPair->value every time an struct was added to the linked list. I had malloc-ed value right under where I malloc 'key'. My reasoning was then that value was pointing at the same memory all the time, so changing 'value' would change the ->value members in all structs, which indeed seemed to be the case. So then I figured that I had to give value a new piece of memory for every record in the linked list.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by django View Post
    I put this line in for the following reason.
    At first, I had value declared just as a char pointer. What then happened was,t hat the pointer firstPair, who is supposed to point at the first record, changed the value for firstPair->value every time an struct was added to the linked list.
    That is because, when you malloc() memory, you are not allocating enough. So, when you assign to any member of firstPair (or, in fact, any of your allocated structs) you are tromping some random area of memory.

    Quote Originally Posted by django View Post
    I had malloc-ed value right under where I malloc 'key'. My reasoning was then that value was pointing at the same memory all the time, so changing 'value' would change the ->value members in all structs, which indeed seemed to be the case.
    Your reasoning is completely broken here. Correct code that changes the value of a variable will never magically change a member of a struct that happens to have the same name. If you see such an effect, it is one of many signs that some other code is tromping over memory it shouldn't.

    I suggest you go back to first principles, and try to understand what sizeof() actually does.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Quote Originally Posted by grumpy View Post
    I've only looked at your malloc() calls. All are broken, so I have not looked further.

    I'll recreate each line here, with a comment showing what each is ACTUALLY equivalent to. Check and see if you are doing what you expect.
    Ok, makes sense. Let me briefly explain my thinking behind every malloc and maybe you can correct any wrong thinking.
    Code:
          char *key = malloc(MAXFIELD * sizeof(*key + 1));       /*   char *key = malloc(MAXFIELD * sizeof(int))   */
    the key in every key=value pair is a string, which gets converted to an int. So my thinking was, I have to reserve the max length of this field. When i convert it to an integer it gets copied, so I can keep reusing this field.
    Code:
         value = malloc(MAXFIELD * sizeof(*value + 1));           /*    value = malloc(MAXFIELD * sizeof(int))  */
    The value field of the key=value pair does not get converted. If I malloc value only one time, it means that the ->value pointers in the struct keyValuePair, all point to the same memory segment which implies that they all point to the same value. This is way I allocate it every time. The size is that of the maximumlength of the fiels + 1 for the \0.

    Code:
         currPair = malloc(sizeof(currPair));                             /*   currPair = malloc(sizeof(struct KeyValuePair *))   */
    My reasoning: currPair points every time to the new record to be added. I need to reserve space for this every time I add a new entry to the linked list. The size is one entry (=key value pair) at a time.

    Curious to have any flaws here pointed out...

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    > char *key = malloc(MAXFIELD * sizeof(*key + 1));
    The thing is, sizeof evaluates the type, not the expression. So sizeof(1) and sizeof(1000) are both the same, namely the size of an int.

    You might want instead
    char *key = malloc(MAXFIELD * ( sizeof(*key) + 1) );



    > currPair = malloc(sizeof(currPair));
    Remember, it is always
    p = malloc(sizeof(*p));

    All you allocated was the size of the pointer, not the size of what it should be pointing to.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Quote Originally Posted by Salem View Post
    > char *key = malloc(MAXFIELD * sizeof(*key + 1));
    The thing is, sizeof evaluates the type, not the expression. So sizeof(1) and sizeof(1000) are both the same, namely the size of an int.

    You might want instead
    char *key = malloc(MAXFIELD * ( sizeof(*key) + 1) );
    Ok, I see what you mean. But the '+1" was merely intended as one extra byte for the '\0'. So I am only 1 off. (but Iguess this can be fatal). Anyway, I corrected it but it does not change anything.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    Then you need to post your latest code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Code:
    struct keyValuePair {
    	int key;
    	char *value;
    	struct keyValuePair *next;
    };
    
    struct keyValuePair *parseMessageString(char *aMessageString) {
    
    	//set walker to the first position of the first key of the message
    	char *walker = aMessageString + strlen(BEGIN);
    	char *end = strstr(aMessageString, END); //this ptr is set at the end of the messg
    	char *sep; //
    
    	char *key = malloc((MAXFIELD * sizeof(*key)) + 1);
    	char *value;
    	int i = 0; //index for key and value pointers
    	int type;  //value for fieldtype
    
    	struct keyValuePair *firstPair = NULL;
    	struct keyValuePair *prevPair;
    	struct keyValuePair *currPair;
    
    	//walk through message string, convert keys into integer
    	//and store key and value in the linked list firstPair
    	while (walker != end) {
    
    		//get key digits untill you encounter '='
    		i = 0;
    		while ((*walker != '=')) {
    			key[i] = *walker;
    			++walker;
    			++i;
    		}
    		key[i] = '\0'; //key[] contains key now
    		type = atoi(key);
    printf("key= %i \n", type);
    	
    		//set sep to next separator or the end for next while loop
    		sep = ((strstr(walker, SEP) == NULL) ? end : strstr(walker, SEP));
    
    		//store the value
    		walker++; //was on the = sign
    		i = 0;
    		value = malloc((MAXFIELD * sizeof(*value)) + 1);
    		if (value == NULL) printf("\nMalloc issue\n");
    		while (walker != sep)
    			value[i++] = *(walker++);
    		value[i] = '\0';//value[] contains now the value
    printf("VAL value= %s\n", value);
    
    		currPair = malloc(sizeof(currPair));
    printf("namallod\n");
    		if (currPair == NULL) printf("\nMalloc Error\n");
    		currPair->key = type;
    		currPair->value = value;
    		currPair->next = NULL;
    
    
    printf("CURR key= %i value= %s\n", type, value);
    		//add cuurPair to the linked list
    		if (firstPair == NULL) {
    			firstPair = currPair;
    			prevPair = currPair;
    		}
    		else {
    			prevPair->next = currPair;
    			prevPair = currPair;
    		}
    		if (sep != end)
    			walker += strlen(SEP);
    	}	
    	return firstPair;
    }

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by django View Post
    Ok, I see what you mean. But the '+1" was merely intended as one extra byte for the '\0'. So I am only 1 off. (but Iguess this can be fatal). Anyway, I corrected it but it does not change anything.
    Surely you aren't confusing sizeof with strlen here -- the sizeof a char is always and forever 1, regardless of how many chars you want to put in it.

    Now, you can't do strlen(key) since key is currently just nothingness, but you can do strlen of whatever you want to copy and then add 1.

    EDIT: Read the words, and not the code -- MAXFIELD does what you want, so never mind, ignore me.
    Last edited by tabstop; 08-27-2011 at 10:32 AM.

  12. #12
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Code:
    currPair = malloc(sizeof(currPair));
    As one/both of the others stated this is WRONG.

    The way below is the common way it is done; also stated by one/both of the others.

    Code:
    currPair = malloc(sizeof(*currPair));
    Quote Originally Posted by Salem View Post
    > currPair = malloc(sizeof(currPair));
    Remember, it is always
    p = malloc(sizeof(*p));

    All you allocated was the size of the pointer, not the size of what it should be pointing to.
    Tim S.
    Last edited by stahta01; 08-27-2011 at 10:25 AM.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    > currPair = malloc(sizeof(currPair));
    Is still wrong.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Quote Originally Posted by Salem View Post
    > currPair = malloc(sizeof(currPair));
    Is still wrong.
    ........ yes I see it now,sorry. My Goodness, this did it, it works. Men, so much trouble over one typo!
    I would still like to know if the thinking behind my malloc's (above) is seriously flawed.
    Thanks, sorry I overlooked the currPair.
    Last edited by django; 08-27-2011 at 10:31 AM.

  15. #15
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by django View Post
    I would still like to know if the thinking behind my malloc's (above) is seriously flawed.
    Yep, sure is...

    You live in a town where all car owners must have a garage ... (C requires you to reserve memory before use)
    You do not have a garage. ( You haven't allocated any memory for storage)
    You just went out and bought a car (You have data you need to store)

    What do you have to do now?

    That's right... you need to build a garage that will hold your car. (You need to allocate memory)

    So, time passes and you decide you don't want a car anymore. (You're done with the data)
    Now you can tear down that ugly garage. (You can free the memory you allocated)


    Really... it's no more complex than that.
    Just make sure you allocate enough memory for each object and free it up when you're done.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. malloc/free of return value
    By Bladactania in forum C Programming
    Replies: 15
    Last Post: 02-10-2009, 01:04 PM
  2. Replies: 3
    Last Post: 11-17-2008, 12:36 PM
  3. Should I cast return value of malloc?
    By movl0x1 in forum C Programming
    Replies: 12
    Last Post: 05-30-2007, 10:22 AM
  4. Replies: 6
    Last Post: 04-09-2006, 04:32 PM
  5. Return values from malloc
    By chambece in forum C Programming
    Replies: 8
    Last Post: 03-24-2006, 01:49 AM