Thread: How must I correctly allocate memory?

  1. #1
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463

    How must I correctly allocate memory?

    The program takes in a command for e.g. "a australia" which adds an ASCII image file with the australian flag into the node. If I type i, it gives an index of all the files added, and if I press p, it prints the flag onto the screen.

    Now these 3 commands work fine to an extent. But if I press "i" to list the files and THEN press "p" it gives me a segfault, however if I don't list the files, i can add and print as many times without any problems. I'm guessing the memory allocation isn't right? But it could be the code.

    Code:
    typedef struct country Country;
    
    struct country {
      char name[LENGTH];
      int dimen;
      int num;
      QTnode *flag; // another structure defined in a nother file
      Country *next;
    };
    char cpy( char s[MAXLENGTH], char strEd[MAXLENGTH] );
    Country *makeNode(char p[MAXLENGTH]);
    // Main function
    int main( void )
    {
      char command[MAXLENGTH];
      char c;
      Country *node;
      Country *pnode;     //previous node
      Country *curr;      //the current node i.e. the most recent file added
      Country *tail = NULL;
      int dimen;
      int i = 1; //This is the image number
      int j;  //This is a control number for the while loop
    
      printPrompt();
    
      while( fgets( command, MAXLENGTH, stdin ) != NULL ) {
    
        int  imgNum;
        char *p;
    
        if(( p=strrchr( command, '\n')) != NULL ) {
          *p = '\0'; // remove '\n' at end of line
        }
        // find the first non-space character in the command
        p = command;
        while(isspace(*p)) {
          p++;
        }
        c = *p;
    
        if( isdigit(c)) {
          if( sscanf( command, "%d", &imgNum ) == 1 ) {
    
            // INSERT CODE FOR <k> COMMAND
          }
        }
        else switch( c ) {
    
        case 'h': // help
    
          printf(" A - Add image\n" );
          printf(" I - Index\n" );
          printf(" P - Print image\n" );
          printf(" F - Forward\n" );
          printf(" B - Back\n" );
          printf("<k>- make image number k the current image\n");
          printf(" D - Delete image\n" );
          printf(" L - Look for image\n" );
          printf(" R - Rotate image counterclockwise\n" );
          printf(" M - Mirror image (reflect vertically)\n" );
          printf("NE - zoom into North East corner\n" );
          printf("NW - zoom into North West corner\n" );
          printf("SW - zoom into South West corner\n" );
          printf("SE - zoom into South East corner\n" );
          printf(" O - zoom Out\n" );
          printf(" U - Undo\n" );
          printf(" H - Help\n" );
          printf(" Q - Quit\n" );
          break;
    
          // INSERT CODE FOR OTHER COMMANDS
    
        case 'a':
          j  = 1;
          while( j > 0 ){       //This loop is actually to allow the image number to increase everytime this case a executes.
          p++;                  
          while(isspace(*p)) { 
          p++;
          }
          node = makeNode(p);                //Create a new node
          curr = node;
          strcpy(node->name, p);             // Copy from the user input to the member 'name' of the struct called node
          node->flag = getImage(node->name, &node->dimen);
          node->num = i;
          if((node->dimen > 0) && (node->dimen < 128)) {
          printf("*%d [%2d] %s\n", node->num, node->dimen, node->name);     //Print details after adding each image
          }
          if( tail == NULL ) {
            tail = node;
            pnode = node;
         }
         else {
            pnode->next = node;
            pnode = pnode->next;
         }
         pnode->next = NULL;
          j = 0;
          i++;
          }
          break;
          
        case 'i':
          node = tail;
          while (node != NULL){
            if(node == curr){
              printf("*%d [%2d] %s\n", node->num, node->dimen, node->name);
            }
            else{
            printf(" %d [%2d] %s\n", node->num, node->dimen, node->name);
            }
            node = node->next;
          }
          break;
          
        case 'p': //print the image
          dimen = node->dimen;  
          printImage(node->flag, dimen);   //accessing the inner node
          break;
    
        case 'q': // quit program
          printf("Bye!\n");
          return 0;
          break;
    
        default:
          printf("Unrecognized command: %s\n", command );
          break;
        }
    
        printPrompt();
      }
    
      return 0;
    }
    
     Country *makeNode(char p[MAXLENGTH]){
    
            Country *node;
            node = (Country*)malloc(sizeof(Country));
            node->next = NULL;
            return (node);
    }
    Last edited by JFonseka; 10-25-2007 at 02:46 AM.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You are mixing LENGTH and MAXLENGTH in places where it seems like you should be consistant.

    It seems like makeNode takes a parameter for a string, but it doesn't use it. To me, it would make sense to move the strcpy() into makeNode, rather than having it inlined in the code. I would pass in "i" as well - but I would like to see it renamed to a more sensible name. "i" is fine for a loop variable, where it's use is obvious to index or count something. Number of entries added isn't such a case.

    Connecting the flag in would be a matter of choice, whether you do that in makeNode or not.

    It seems like "tai" is a bit misnamed, since it seems like using tail as "head". pNode is tail.

    "p" doesn't work after "i" becuase "i" stops when the list is empty -> node = NULL -> seg-fault.

    You shouldn't need to cast malloc - see the FAQ. If you get warnings or errors, it's etiher because you don't include the stdlib.h header, or you are using a C++ compiler to compile C - the compiler will have some switch that tells it whether it should accept the code as C or C++.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Ok I renamed i to "img"

    And I moved the strcpy into the makeNode function

    I have all the library headers, I just didn't paste them into the post.

    And yea tail is essentially the head, I used that code from an example in a book, and just renamed head into tail, didn't think it would make a difference.

    I still don't get why there is a segfault when pressing "p" after "i" because "p" is meant to print the most recently added image. And the list printing the index of images shouldn't affect the image in memory
    Last edited by JFonseka; 10-25-2007 at 02:47 AM.

  4. #4
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Ahh I get you know. I just changed it to pnode, because that is always the last node anyways.

    Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Promblem with code
    By watchdogger in forum C Programming
    Replies: 18
    Last Post: 01-31-2009, 06:36 PM
  2. Memory allocation and deallocation
    By Micko in forum C++ Programming
    Replies: 3
    Last Post: 08-19-2005, 06:45 PM
  3. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM
  4. Memory handler
    By Dr. Bebop in forum C Programming
    Replies: 7
    Last Post: 09-15-2002, 04:14 PM
  5. How do I use malloc to allocate memory for a linked list?
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 09-14-2001, 01:02 PM