Thread: help with structs and malloc!

  1. #1
    Registered User
    Join Date
    Sep 2009
    Posts
    16

    help with structs and malloc!

    I'm writing a header files and I must be allocating the space wrong because I'm trying to do a linked list but the nodes keep changing.

    table.h (some of these I haven't written yet)
    Code:
    #ifndef TABLE_H_
    #define TABLE_H_
    #include <stdio.h>
    
    	struct lineNode;
    
    	struct entry;
    
    	struct table;
    
    	/* returns an empty table */
    	struct table * newTable ( );
    
    	/* returns the result of adding a definition for the given symbol
    	   in the line with the given number to the table */
    	struct table * addDef (char * symbol, int lineNum, struct table * symbols);
    
    	/* returns the result of adding a use of the given table in the line
    	   with the given number to the table */
    	struct table * addUse (char * symbol, int lineNum, struct table * symbols);
    
    	/* print the table, in the format described above, to the given file */
    	void printTable (struct table * symbols, FILE * out);
    
    
    
    #endif /* TABLE_H_ */
    table.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "table.h"
    
    struct lineNode {
      int lineoccur;
      struct lineNode *next;
    };
    
    struct entryNode {
    	struct entryNode *next;
    	struct entry *row;
    };
    
    struct entry {
           char * symbol;
           int linedef;
           struct lineNode *occur;
    };
    
    struct table {
           int entrycount;
           struct entryNode *first;
    };
    
    	/* returns an empty table */
    struct table * newTable( ) {
           struct table * table1 = malloc(sizeof(struct table));
           table1->entrycount = 0;
           return table1;
    }
    
    struct table *firstSymbol(struct table * symbols) {
    	printf("the symbol is %s\n", symbols->first->row->symbol);
    }
    
    	/* returns the result of adding a definition for the given symbol
    	   in the line with the given number to the table */
    struct table * addDef (char * symbol, int lineNum, struct table * symbols){
    
    	printf("adding %s\n", symbol);
    	printf("entrycount is %d\n", symbols->entrycount);
    	if (symbols->entrycount == 1)
    		printf("should be word1 %s\n", symbols->first->row->symbol);
    
    	struct entry *newEntry = malloc(sizeof(struct entry));
    	newEntry->symbol = symbol;
    	newEntry->linedef = lineNum;
    	struct entryNode *newEntryNode = malloc(sizeof(struct entryNode));
    	newEntryNode->row = &newEntry;
    
            //somewhere here the symbol in the first node changed to "word2"
    	if (symbols->entrycount == 1)
    			printf("again should be word1 %s\n", symbols->first->row->symbol);
    
    	if (symbols->entrycount == 0) {
    		symbols->first = &newEntryNode;
    		symbols->entrycount = 1;
    		printf("should be word1 %s\n", symbols->first->row->symbol);
    	}
    	else {
    		printf("2should be word1 %s\n", symbols->first->row->symbol);
    		struct entryNode *nEntryNode = malloc(sizeof(struct entryNode));
    		nEntryNode = symbols->first;
    		int s = symbols->entrycount;
    		while (s != 1) {
    			nEntryNode = nEntryNode->next;
    			s--;
    		}
    		nEntryNode->next = &newEntryNode;
    
    	}
    	printf("should still be word1 %s\n", symbols->first->row->symbol);
    	return symbols;
    }
    
    	/* returns the result of adding a use of the given table in the line
    	   with the given number to the table */
    //struct table * addUse (char * symbol, int lineNum, struct table * symbols) {
    //    return symbols;
    //}
    
    	/* print the table, in the format described above, to the given file */
    void printTable (struct table * symbols, FILE * out) {
        struct entryNode *n = symbols->first;
        printf("%s\t\n", n->row->symbol);
        printf("%d\t\n", n->row->linedef);
        printf("here it is\n");
    }
    tabletest.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "table.h"
    
    main() {
    
    
        struct table *p = newTable();
        p = addDef("word1", 1, p);
        p = addDef("word2", 2, p);
        printTable(p, "out.txt");
    
        return 0;
    
    }
    This is the output I get on eclipse:
    adding word1
    entrycount is 0
    should be word1 word1
    should still be word1 word1
    adding word2
    entrycount is 1
    should be word1 word1
    again should be word1 word2
    2should be word1 word2
    should still be word1 word2
    0Ì"
    2280496
    here it is

    Why is it printing out a weird symbol and letter? And if I'm using malloc how did the contents change to word2 when I was creating new nodes and not assigning anything to it?

    Thanks in advance.

  2. #2
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    How about assigning all members of the declared structs. By leaving out some you can expect the weird symbols in the output
    Code:
    struct table * newTable( ) {
           struct table * table1 = malloc(sizeof(struct table));
           table1->entrycount = 0;
           return table1;
    }
    Where's the assignment for struct entryNode *first member of struct table.

  3. #3
    Registered User
    Join Date
    Sep 2009
    Posts
    16
    hmm I don't know if that makes a difference... I was checking the addresses of the places where the first->symbol is stored, when I have this in addDef

    Code:
            printf("2should be word1 %d\n", symbols->first->row->symbol);
    	}
    	struct entry *newEntry = (struct newEntry*) malloc(sizeof(struct entry));
    	printf("address is %d\n", newEntry);
    
    	if (symbols->entrycount == 1) {
    					printf("3here again should be word1 %d\n", symbols->first->row->symbol);
    					printf("4here again should be word1 %s\n", symbols->first->row->symbol);
    	}
    
    	newEntry->symbol = symbol;
    	newEntry->linedef = lineNum;
    
    	if (symbols->entrycount == 1) {
    		printf("5here again should be word1 %d\n", symbols->first->row);
    		printf("6here again should be word1 %s\n", symbols->first->row->symbol);
    	}
    part of the output is:
    1should be word1 word1
    2should be word1 134515162
    address is 165683272
    3here again should be word1 0
    4here again should be word1 (null)
    5here again should be word1 165683272
    6here again should be word1 word2

    So it seems like after I initialized newEntry it also changed symbols->first->row->symbol? and later set it to the newEntry? how did that happen?

  4. #4
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    your initial code in your first post compiled with the following warnings:
    Quote Originally Posted by gcc
    table.c: In function `addDef':
    table.c:31: warning: assignment from incompatible pointer type
    table.c:38: warning: assignment from incompatible pointer type
    table.c:51: warning: assignment from incompatible pointer type
    referring to lines which do something like:
    Code:
    newEntryNode->row = &newEntry;
    newEntryNode->row is of type struct entry * but your passing type of struct entry **. fixing these warnings produced correct output for me.

    also, for every malloc call you must have a corresponding free call; your program has a few memory leaks in it.

  5. #5
    Registered User
    Join Date
    Sep 2009
    Posts
    16
    wow ok fixing the warnings seemed to have worked. thanks!

    what do you mean I have to free the malloc? I want to add to the linked list so how else would I keep creating new nodes and add to the existing ones?

  6. #6
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    also:
    Code:
    struct entryNode *nEntryNode = malloc(sizeof(struct entryNode));
    nEntryNode = symbols->first;
    this is another memory leak because you allocate some memory and assign the address of this allocated memory to nEntryNode. however, the next line you assign a different value to nEntryNode, thus loosing the address of the initial memory you allocated, and you now have no way of freeing or either referencing this memory. basically, the malloc call is not needed, just do:
    Code:
    struct entryNode *nEntryNode = symbols->first;

  7. #7
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    wow ok fixing the warnings seemed to have worked. thanks!
    make sure to pay attention to all compiler output, warnings are just that: warnings. its saying "ATTENTION: did you mean to do this? if not, the behaviour might not be what you intended".

    what do you mean I have to free the malloc?
    if you dont fully understand what dynamic memory is (in particular, the calls to malloc and free in the C language), i would suggest reading an overview of it (or check the FAQ on this site, there should be an entry for this topic). when you call "malloc", your telling the OS "i want N bytes of memory allocated to me, and i will manage it completely". the OS searches for a continuous block of N available bytes of RAM, and if it finds some it gives it to you. if it doesnt find some, it returns NULL (therefore you should check the return value of malloc) and your program doesnt get this memory (and it should exit with an error or appropriate message). if you get the memory, you can do whatever you want with it. when you are done with it, you must free the memory with the "free" function call. if you dont "free" it, when your program is done running, the OS still has this memory reserved for your program, however its not being used--its wasted and you cant do anything about it. on some OSs, this memory leak continues until the machine is restarted. there may be other OSs or some tools to use to clean this stuff up (though i dont know of any).

    I want to add to the linked list so how else would I keep creating new nodes and add to the existing ones?
    the else block in your addDef function should be changed to something like:
    Code:
    struct entryNode *nEntryNode = symbols->first;
    while ( nEntryNode->next != NULL ) { // use either "0" or "NULL", if you use "NULL" then define it or include the header its defined in (if there is one, i forget)
           nEntryNode = nEntryNode->next;
    }
    nEntryNode->next = newEntryNode;
    this loop iterates over all nodes, starting at the first, and stopping when this node does not have a next, which means its at the end of the list. you then add your new node at this spot ("next"). this logic assumes that whenever you create a newNode, you assign its next to "0" or "NULL', otherwise the algorithm doesnt work. this is usually how linked lists are implemented. therefore, you need to make sure to set the next to this value whenever you create one.

    tell us if you understand this, otherwise it is completely useless if you can copy and paste it without understanding (in which case i will wish i wouldnt have given you the information).
    Last edited by nadroj; 09-13-2009 at 01:44 PM. Reason: grammar

  8. #8
    Registered User
    Join Date
    Sep 2009
    Posts
    16
    ok so I made all those fixes, and now I'm writing another function addUse, which adds a node containing a number to the *occur list of entry objects to the table.

    Code:
    struct table * addUse (char * symbol, int lineNum, struct table * symbols) {
    
    	
            //when I add in this printf line, it runs fine
            printf("starting to add %s %d\n", symbol, lineNum);
    	struct entry *nEntry = symbols->first;
    	while ( nEntry->symbol != symbol) {
    		if (nEntry->next == NULL) {
    			printf("should not be null\n");
    			break;
    		}
    		nEntry = nEntry->next;
    	}
    	struct lineNode *o = nEntry->occur;
    	while ( (o->next != NULL) && (o->lineoccur != -1) ) {
    		o = o->next;
    	}
    
    	if (o->lineoccur == -1) {
    		o->lineoccur = lineNum;
    	}
    	else {
    		struct lineNode *newLineNode = malloc(sizeof(struct lineNode));
    		newLineNode->lineoccur = lineNum;
    		o->next = newLineNode;
    	}
    
    	return symbols;
    }
    this is the printTable function that is printing out the table
    Code:
    void printTable (struct table * symbols, FILE * out) {
        struct entry *n = symbols->first;
    
    	while (n != NULL) {
        	printf("%s\t", n->symbol);
        	printf("%d\t", n->linedef);
    
        	struct lineNode *nline = n->occur;
    
        	while ((nline != NULL) && (nline->lineoccur != -1)) {
        		printf("%d\t", nline->lineoccur);
        		nline = nline->next;
        	}
        	printf("\n");
    
        	fprintf(out, "%s\t", n->symbol);
        	fprintf(out, "%d\t\n", n->linedef);
        	n = n->next;
        }
    
    	printf("finished printing \n");
    }
    If I don't have the print line, this is what I get on eclipse:
    13 [main] hw3 13744 _cygtls::handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
    930 [main] hw3 13744 open_stackdumpfile: Dumping stack trace to hw3.exe.stackdump

    how can a print statement change it?

    If I add in the print line:
    starting to add word1 11
    starting to add word2 5
    starting to add word2 6
    starting to add word2 7
    starting to add word2 8
    starting to add word2 9
    starting to add another word! 3
    starting to add another word! 4
    word1 1 11
    word2 2 5 6 7 8 9
    another word! 12 3 4
    finished printing

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You never set 'newLineNode->next' to anything.


    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    Sep 2009
    Posts
    16
    thanks for all the help I've gotten! it's very useful.

    now I'm writing a processLines that will assign each word in a line read in to addDef or addUse to add to my table.

    processLines
    Code:
    int processLine(char *s, int linecount) {
    	printf("string is %s\n", s);
    
    	if (emptyLine(s) == -1) {
    		return 0;
    	}
    	else {
    		char word[MAXSYMBOL];
    		int pos = 0;
    		char c = *s;
    		//hi
    		int wordon = 0;
    		printf("c is %c\n", c);
    		while (c != '\n' && c != EOF && c!='#') {
                            //when I add this line in it starts to infinite loop
    			printf("c is %c\n", c);
    			if (c == ' ' && wordon == 0) {
    				s++;
    				c = *s;
    			}
    			else if (c != ' ' && wordon == 0){
    				word[pos] = c;
    				s++;
    				pos++;
    				c = *s;
    				wordon = 1;
    			}
    			else if (c == ' ' && wordon == 1) {
    				printf("word ended %s\n", word);
    				wordon = 0;
    				s++;
    				c = *s;
    			}
    			else {
    				word[pos] = c;
    				pos++;
    				s++;
    				c = *s;
    			}
    
    		}
    		return 0;
    	}
    
    }
    I am calling processLines in my main() with the line "abc " from my input file. The first time the c prints it prints fine, 'a' but then in the while loop it starts to infinite loop.

    here is emptyLine
    Code:
    int emptyLine (char line[]) {
        int i=0;
        while (1) {
        	printf("line[i] is %c\n", line[i]);
              if (line[i] == '\0' || line[i] == '\n') {
                 return -1;
              }
              else if (line[i] != ' ') {
            	  printf("should not be empty\n");
                   return i;
              }
              else {
                   i++;
              }
        }
    }

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    How do you plan to get out of your while loop? You can't. You should maybe check for the end of string character (which is '\0', not EOF).

  12. #12
    Registered User
    Join Date
    Sep 2009
    Posts
    16
    ok I fixed the '\0' problem by adding two more cases:

    Code:
    int processLine(char *s, int linecount, struct table *p) {
    	printf("string is %s\n", s);
    	char words[MAXSYMBOL];
    
    	char* word = words;
    
    	char* word2 = word;
    
    	if (emptyLine(s) == -1) {
    		return 0;
    	}
    	else {
    		//char word[MAXSYMBOL];
    		int pos = 0;
    		char c = *s;
    		//hi
    		int wordon = 0;
    		printf("c is %c\n", c);
    		while (c != '\n' && c != EOF && c!='#') {
    			printf("c is %c\n", c);
    			if (c == ' ' && wordon == 0) {
    				s++;
    				c = *s;
    			}
    			else if (c != ' ' && wordon == 0){
    				*word = c;
    				word++;
    				s++;
    				pos++;
    				c = *s;
    				wordon = 1;
    			}
    			else if (c == '\0' && wordon == 0) {
    				*word = '\0';
    				break;
    			}
    			else if (c == '\0' && wordon == 1) {
    				printf("line ended %s\n", word);
    				*word = '\0';
    				addDef(word2, linecount, p);
    				break;
    			}
    			else if (c == ' ' && wordon == 1) {
    				*word = '\0';
    				printf("word ended2 %s\n", word);
    				wordon = 0;
    				s++;
    				c = *s;
    			}
    			else {
    				*word = c;
    				word++;
    				pos++;
    				s++;
    				c = *s;
    			}
    
    		}
    
    		return 0;
    	}
    
    }
    I want to read in every word, add the word to the table, and when I reach '\0' stop, so I switched over to using pointers. However, now I get a jumble when I print out the word I read. Why is this?

    c is a
    c is a
    c is b
    c is c
    c is
    c is
    line ended ø]¿KÑ°À¤À

    Ô]¿KÑ°À¤À
    1
    finished printing
    stack trace 2
    Ô]¿ø]¿Ø³ 1 2

    I should have had "abc" added instead.

  13. #13
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by nadroj View Post
    if you dont "free" it, when your program is done running, the OS still has this memory reserved for your program, however its not being used--its wasted and you cant do anything about it. on some OSs, this memory leak continues until the machine is restarted. there may be other OSs or some tools to use to clean this stuff up (though i dont know of any).
    Isn't it that the when the program has executed properly, the allocated memory is automatically freed and can be used somewhere else?
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  14. #14
    Registered User
    Join Date
    Sep 2009
    Posts
    16
    Quote Originally Posted by BEN10 View Post
    Isn't it that the when the program has executed properly, the allocated memory is automatically freed and can be used somewhere else?
    but I haven't used malloc in this function?

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You need to figure out why you didn't get "word ended2" -- you are soooo not going to get the word printed on the line, since by definition word is completely blank (your word is in word2, not word). But I don't see any reason why you didn't get in there, so you need to see what happened to wordon. And of course if you didn't get into that particular bit of code, obviously nothing was added to your table. Are you sure you have a space at the end of your word? (Edit: And of course, having code that doesn't add a word to the list if there's not a space on it is probably an error on its own, so when the character is \0 and wordon is 1, you should probably add to the table there too.)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Malloc for an Array of Structs
    By pseudonoma in forum C Programming
    Replies: 3
    Last Post: 03-26-2008, 01:55 PM
  2. Malloc with structs.
    By jrdoran in forum C Programming
    Replies: 4
    Last Post: 12-11-2006, 11:26 PM
  3. malloc for structs and arrays
    By rkooij in forum C Programming
    Replies: 15
    Last Post: 05-04-2006, 07:38 AM
  4. malloc
    By bazzano in forum C Programming
    Replies: 3
    Last Post: 04-19-2006, 09:53 AM
  5. Creating a pointer to an array of structs
    By Jonathan_ingram in forum C Programming
    Replies: 8
    Last Post: 12-31-2003, 08:49 AM