Thread: Memory access I can't get

  1. #1
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751

    Memory access I can't get

    I'm coding this CGI program in C and seem to be having some memory violations. Intially i coded it and the code returned a char *, however when i asked in main to print the value there with puts. my code crashed, however i could do so with printf.

    In order to have it work better, i coded it again, and now this time my code seems to just crashes. I have no idea where the seg fault is as i've been staring at it for a while. Please let me know if you need to see the additional functions. However they seem to work fine, as this was the only code i changed.

    Code:
    #include <stdio.h>
    #include <stdlib.h> // for getenv. don't implicitly call this function
    #include <string.h>
    #include "CGINCform.h"
    
    char *getvalue(char *name){
    if( (getenv("REQUEST_METHOD")) =="post"){
    	 /*length of info from stdin,buffer for url, temp and return value of nameValue()*/
    	 char *formLength;
    	 char *url;
    	 char *Temp;
    	 char *ValueOfName;
    	 unsigned long INPUT;/*size of input from stdin*/
    	 
    	 /*get form length and convert to a number.*/
    	 formLength = getenv("CONTENT_LENGTH");
        INPUT = atol(formLength);
        
        /*make sure room available on system to store info from stdin*/
        if ((url = malloc( (INPUT+1) * sizeof(char) ) ) == NULL){
       perror("No room Allocated for url");
       return NULL;
       }
       
        if ((Temp = malloc((INPUT+1) * sizeof (char) ) ) == NULL){
       perror("No room allocated for Temp");
       return NULL;
       }
    
      /*get info from stdin and store accordingly */
       
       if( ( fgets(url,INPUT,stdin) ) !=NULL){
       decodeUrl(url); 
       hex2Dec(Temp,url); /*copies url to temp and transforms it */
       /*look for the value of name in temp which is up to INPUT and returns its address*/
       ValueOfName=nameValue(Temp,INPUT,name);
       free(url);/*isn't used anymore copied into temp by hex2Dec*/
       //free(Temp);
       }/*end of info processing info from STDIN */
    
    return ValueOfName;	 
    }/*end of 1st if block and succesful input from stdin */
    
    else 
    
    return NULL;/*no  valid HTTP method given end of if branch */
    
    }/*end of function getvalue.c */
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    if( (getenv("REQUEST_METHOD")) =="post")
    getenv returns a pointer to a character string. You cannot use the == operator to compare for equality with character pointers. You need to use strcmp (or even stricmp).

    Code:
    /*get form length and convert to a number.*/
    formLength = getenv("CONTENT_LENGTH");
    INPUT = atol(formLength);
        
    /*make sure room available on system to store info from stdin*/
    if ((url = malloc( (INPUT+1) * sizeof(char) ) ) == NULL){
    All of this code depends on the getenv call succeeding. You need to make sure you get a non-NULL value before you go through converting to a numerical value and malloc'ing memory.

    Don't know if those will fix your problem, but addressing those concerns would be prudent.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    they should make a emoticon so you can smack your hand against your forhead. I've fixed the comaprison problem. But Code still crashes. Any ideas?
    Code:
    #include <stdio.h>
    #include <stdlib.h> // for getenv. don't implicitly call this function
    #include <string.h>
    #include "CGINCform.h"
    
    char *getvalue(char *name){
    	 
    if( (strcmp(getenv("REQUEST_METHOD"),"POST"))==0){
    	 /*length of info from stdin,buffer for url, temp and return value of nameValue()*/
    	 char *formLength;
    	 char *url;
    	 char *Temp;
    	 char *ValueOfName;
    	 unsigned long INPUT;/*size of input from stdin*/
    	 
    	 /*get form length and convert to a number.*/
    	 formLength = getenv("CONTENT_LENGTH");
        INPUT = atol(formLength);
        
        /*make sure room available on system to store info from stdin*/
        if ((url = malloc( (INPUT+1) * sizeof(char) ) ) == NULL){
         perror("No room Allocated for url");
         return NULL;
        }
       
        if ((Temp = malloc((INPUT+1) * sizeof (char) ) ) == NULL){
        perror("No room allocated for Temp");
        return NULL;
       }
    
      /*get info from stdin and store accordingly */
       
       if( ( fgets(url,INPUT,stdin) ) !=NULL){
       decodeUrl(url); 
       hex2Dec(Temp,url); /*copies url to temp and transforms it */
       /*look for the value of name in temp which is up to INPUT and returns its address*/
       ValueOfName=nameValue(Temp,INPUT,name);
       free(url);/*isn't used anymore copied into temp by hex2Dec*/
       //free(Temp);
       }/*end of info processing info from STDIN */
    
    return ValueOfName;	 
    }/*end of 1st if block and succesful input from stdin */
    
    else 
    
    return NULL;/*no  valid HTTP method given end of if branch */
    
    }/*end of function getvalue.c */
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by caroundw5h
    But Code still crashes. Any ideas?
    Do you have a small, but complete, sample that demonstrates the problem? The other functions that we cannot see, and without which we cannot compile or link, may be the problem. Maybe hard-code some of the getenv data, too.

    You've been playing 20 questions with this for a while (apparently to avoid doing this), but it is your fastest route to a solution -- whether you find it by yourself in the process of trying to isolate it, or whether you get a very fast response here or elsewhere to a well-specified question.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    &dave looks like you've been lurking all over.
    here is the code. Its really annoying. More so because the first form seemed to work and then the second completly crashed and I don't just want to fix it. I want to understand why. Some have suggested I'm calling memory I've already freed but I can't see where.
    here is some code.
    the getenv function returns values of my environment and that is hard code html i'm running on a local server. but at least the functions can give you an idea.
    here is getvalue and the subsequent functions it calls: decodeUrl,hex2dec(yours :d) and nameValue in that order.
    Code:
    #include <stdio.h>
    #include <stdlib.h> // for getenv. don't implicitly call this function
    #include <string.h>
    #include "CGINCform.h"
    
    char *getvalue(char *name){
    	 
    if( (strcmp(getenv("REQUEST_METHOD"),"POST"))==0){
    	 /*length of info from stdin,buffer for url, temp and return value of nameValue()*/
    	 char *formLength;
    	 char *url;
    	 char *Temp;
    	 char *ValueOfName;
    	 unsigned long INPUT;/*size of input from stdin*/
    	 
    	 /*get form length and convert to a number.*/
    	 formLength = getenv("CONTENT_LENGTH");
        INPUT = atol(formLength);
        
        /*make sure room available on system to store info from stdin*/
        if ((url = malloc( (INPUT+1) * sizeof(char) ) ) == NULL){
         perror("No room Allocated for url");
         return NULL;
        }
       
        if ((Temp = malloc((INPUT+1) * sizeof (char) ) ) == NULL){
        perror("No room allocated for Temp");
        return NULL;
       }
    
      /*get info from stdin and store accordingly */
       
       if( ( fgets(url,INPUT,stdin) ) !=NULL){
       decodeUrl(url);/*parses and changes url */
       hex2Dec(Temp,url); /*copies a changed url to temp*/
       /*look for the value of name in temp which is up to INPUT and returns its address*/
       ValueOfName=nameValue(Temp,INPUT,name);
       //free(url);/*isn't used anymore copied into temp by hex2Dec*/
       //free(Temp);
       }/*end of info processing info from STDIN */
    
    return ValueOfName;	 
    }/*end of 1st if block and succesful input from stdin */
    
    else 
    
    return NULL;/*no  valid HTTP method given end of if branch */
    
    }/*end of function getvalue.c */
    decodeUrl:
    Code:
    #include "CGINCform.h"
    
    void decodeUrl(char *str){
          int *FILEDS= 0;
        /* only really usable ascii characters are from d32 to d127 but it starts from
        0 to 255. So might as well just parse everything and have the computer do its job */
        
      getenv("QUERY_STRING")? puts(" using GETS") : puts (" using POST");
     
      
        /*this function looks for all the characters '+' and '&' and replaces them with
        a space and a '\n' respectively. It also converts all hexadecimal values to their
        decimal equivalent. 
        IMPORTANT: Converting hexx to decimal should not be done on textarea inpput and 
        other text type input in case end user meant for that to happen */
        while (*str++ ){
            if ( *str == '+')
               *str = ' ';
               
               
            if ( *str == '&')
              *str = '\n';
              FILEDS+=1;//counts the number of name vlaue pairs and is sent to getValue()
              
          }
      }
    hex2Dec:
    Code:
    #include "CGINCform.h"
    #include <stdio.h>
    
    char *hex2Dec(char *dst, const char *src)
    {
       int i, j = 0;
       for ( i = 0; src[i]; ++i)
       {
          if ( src[i] != '%' )
          {
             dst[j++] = src[i];
             
             /*only put everythng not a '%' in dest buffer */
          }
          else //if its a '%' 
          {
             unsigned ch;
             if ( sscanf(&src[++i/* skip '%' */], "%2x"/*read 2 hex characteres */, &ch) != 1 )
             /*scan data for hex values up to 2field width assign to ch
             this is done because string is a long sequence with no spaces. if spaces
             wouldn't have to use width specifier to tell how many numbers to read
             would automatically read the hex number
             for intelectual curiouslity: &src(i++... */
             {
                return NULL;// if not a hex character retrun null. interesing seems scanf won't 
                //act stupid if it's not you can let it do what you want it to.
             }
             dst[j++] = ch;// assign hex to to dest. is hex converted to deciaml then
             ++i; /* with the loop's increment, this will skip the 2nd hex chars 
             intellectual curiousity: i++ */
          }
       }
       dst[j] = '\0';
       return dst;
    }
    NameValue
    Code:
    #include <stdio.h>
    #include <string.h>
    #define MAXFIELDS 100
    /*gonna have to rename nameValue to getvalue which will accept
    getvalue(char *url,int length, char *name)
    can't think of anything else right now.
    */
    char* nameValue(char *URL,int len,char *name ){
         /*make len already known and rename key to name. 
         this function returns the value of a name value pair */
       char names[MAXFIELDS][MAXFIELDS],values[MAXFIELDS][MAXFIELDS],temp[MAXFIELDS];
       char *word;
        int ndx;
        int posNum=0;
        int ndx2=0;
        /*we use a second counter becuase we'll have to reset it to zero without
        stopping iteration of the url */
     for (ndx=0;ndx<len;ndx++){   
        temp[ndx2++] = URL[ndx];
          
          
            if ( (URL[ndx] == '=') ){
                 temp[ndx2-1] = '\0';
                 strcpy(names[posNum],temp);
                 ndx2=0; //reset buffer to indx 0 for next word
              }
               
           else if( (URL[ndx] == '\n') ){
                temp[ndx2-1] = '\0';
                strcpy(values[posNum],temp);
                ndx2=0;
                posNum+=1;//the word postion only changes after a '\n'
             }      
    }
    
    //this prints the name value pairs per line to test it works in stdout 
    int i;
       for(i=0;i<posNum;i++)
          printf("%s = %s<br>", names[i],values[i]);
    
          
      for (ndx=0;ndx<posNum;ndx++){
             if( (strcmp(names[ndx],name)) ==0)
               word = values[ndx];
               
             }//end of 2nd for 
             return word;
          }
    Main:
    Code:
    /* basic CGI program in C allows 
    one to receive form values and 
    manipulate them.
    */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "CGINCform.h" 
    
    int main(void){
    /*once CGINCform has done all the work - gather input,parse data,decode data
    and return the value of the name looking for. Your now ready to write whatever
    you want back to stdout - that is your webbrowser client. CGINCform returns
    a char * to the value of the name given as its parameter. What you do with it is up to you 
    */
        char *Identifier;
        Identifier = "Comments";/*store addy of HTML Identifier */
        char *x;
    	 x=getvalue(Identifier);/*store return addy of getvalue */
       
      /*inform browser of the content type to display */  
      printf("Content-type: text/html\n\n");
      
      /*write html code to display */
      printf("<html>\n");
      puts("<head> <title> CGINCform</title> </head>");
      printf("<body bgcolor = \"purple\">\n");
      /*on another module enumerate a list of colors and have user select */
      
      printf("<center> <h1>CGINC</h1> </center>");
      puts("<br>");
    
     puts(x);
     printf("<br>%s",x );
     puts("</body>");
     printf("</html>\n");
      /*end of html output */
    
    return 0;
    }
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    I may add more things as edits as I'm picking lint.
    Code:
    void decodeUrl(char *str)
    {
       int *FILEDS= 0; /* this is a null pointer */
    Did you want it to be an int?

    Code:
    char* nameValue(char *URL,int len,char *name )
    {
       /*... */
       char *word;
       /*... */
       for ( ndx=0;ndx<posNum;ndx++ )
       {
          if ( (strcmp(names[ndx],name)) ==0 )
             word = values[ndx];
       }//end of 2nd for
       return word;
    }
    Red flags abounding! Did you mean to malloc some memory for word?

    An aside:
    Code:
       while ( *str++ )
       {
          if ( *str == '+' )
    I think you'd probably want to increment at the end of the loop.
    Last edited by Dave_Sinkula; 03-03-2005 at 11:12 AM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Quote Originally Posted by Dave_Sinkula
    I may add more things as edits as I'm picking lint.
    Code:
    void decodeUrl(char *str)
    {
       int *FILEDS= 0; /* this is a null pointer */
    Did you want it to be an int?
    I did want it to be and integer. is assigning '0' to a pointer on init, short for pointing it to NULL. How do i circumvent that.


    Code:
    char* nameValue(char *URL,int len,char *name )
    {
       /*... */
       char *word;
       /*... */
       for ( ndx=0;ndx<posNum;ndx++ )
       {
          if ( (strcmp(names[ndx],name)) ==0 )
             word = values[ndx];
       }//end of 2nd for
       return word;
    }
    Red flags abounding! Did you mean to malloc some memory for word?
    i only wanted this function to point to the address of the word so i could dereference it later. Should i have used malloc somewhere and why.
    thank you so much for your help. red flags all you want!!
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    First, I think word is the key. It is either an uninitialized pointer, or it points to local data. Returning it from this function will cause hell if it is used elsewhere.

    WRT FILEDS, if you just want an int, do just that.
    Code:
    int FILEDS= 0;
    And did you really mean FIELDS?
    Last edited by Dave_Sinkula; 03-03-2005 at 11:21 AM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  9. #9
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    yeah i did mean "FIELDS"
    I made it a pointer because i wanted to pass it to another function.

    now about word. "Returning it from this function will cause hell if it is used elsewhere."
    why is that? am i not just returning the address. is that not legal
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  10. #10
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I made it a pointer because i wanted to pass it to another function.
    FILEDS is just a pointer to an int which supposedly resides at address 0 from your initialization. Then you're incrementing FILEDS will means that it's now a pointer to an int that resides at address 0+sizeof(int). The next time you increment it, you're saying FILEDS is a pointer to an int at memory address 0+sizeof(int)+sizeof(int). You can see the problem here. You're not actually making an int and using it as a counter. You're making a pointer to a non-existent int and keep telling it to point to another non-existent int every time you increment it. I don't see where you're passing it to another function, so I'd just drop the * from the declaration so it's a normal run-of-the-mill int which is what it looks like you want.
    now about word. "Returning it from this function will cause hell if it is used elsewhere."
    why is that? am i not just returning the address. is that not legal
    Yes, you're returning the address. The problem is, the memory address that it points to becomes invalid when the function returns. The values array is declared as an automatic variable local to that function, so when the function returns, the memory at that address is reused for whatever comes next.
    If you understand what you're doing, you're not learning anything.

  11. #11
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    FILEDS is just a pointer to an int which supposedly resides at address 0 from your initialization. Then you're incrementing FILEDS will means that it's now a pointer to an int that resides at address 0+sizeof(int). The next time you increment it, you're saying FILEDS is a pointer to an int at memory address 0+sizeof(int)+sizeof(int). You can see the problem here. You're not actually making an int and using it as a counter. You're making a pointer to a non-existent int and keep telling it to point to another non-existent int every time you increment it. I don't see where you're passing it to another function, so I'd just drop the * from the declaration so it's a normal run-of-the-mill int which is what it looks like you want.
    I didn't realize i was incrementing the pointer at all!! wow. So if i wanted to use a poitner to store an integer how would that be done. do i need to typecast it to an int? As it stands my intention was to use it in another function but i never got around to it. discarding it is of no consequnce to the code. so if i do
    Code:
    int *ptr_int;/*allocate space to store the address of an int */
    ptr_int = 1;
    does that not contain the addy of where 1 is stored now? or was it just a special case with initing it with 0?


    Yes, you're returning the address. The problem is, the memory address that it points to becomes invalid when the function returns. The values array is declared as an automatic variable local to that function, so when the function returns, that memory address is reused for whatever comes next.
    I actually saw this answered on a site before and can't remember where. How would i fix this. Copy the value of word to a string and return the string, or declare the arrays globally?
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  12. #12
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Quote Originally Posted by caroundw5h
    so if i do
    Code:
    int *ptr_int;/*allocate space to store the address of an int */
    ptr_int = 1;
    does that not contain the addy of where 1 is stored now? or was it just a special case with initing it with 0?
    What that code does is make a pointer to an int that supposedly exists at memory address 1. If you want to have a counter variable that you can pass to another function and let that function update it, you could just create a normal int and then pass the address of that int to the function, so the receiving function would have a pointer to that int. Or you could do something like this:
    Code:
    {
      int ctr ;
      int *ctr_ptr = ctr;
    
      /* ctr = 0 and *ctr_ptr = 0 will both accomplish setting ctr to 0 */
    
      (*ctr_ptr)++;
    }
    That way you're actually allocating space for an int, and then you're creating a pointer to that int. To increment ctr then you dereference ctr_ptr and increment that. The parentheses are necessary because without them you're incrementing the pointer instead of incrementing the dererenced int.

    Quote Originally Posted by caroundw5h
    I actually saw this answered on a site before and can't remember where. How would i fix this. Copy the value of word to a string and return the string, or declare the arrays globally?
    You have a few choices:
    1) Declare value as a static array. This way the memory address remains valid even after the function returns.
    2) malloc() memory for word and then copy the string to it. Don't forget to free() the memory after using it in the calling function though.
    3) Make value a global variable. This is usually a discouraged work-around.
    4) Pass a buffer to the function in which to store the string. So you'd use the buffer passed to the function instead of the local word variable. This would be my preferred choice.
    If you understand what you're doing, you're not learning anything.

  13. #13
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    What that code does is make a pointer to an int that supposedly exists at memory address 1.
    I'm creating a new acronym. WAFM (what a f****** moron) at me. I knew that. I don't know what I even asked you that question . looking back on it now I clearly see that i was incrementing the address!!! aaaughghghghgh!!!! I'm sorry man, i can't believe that!!!

    as to the options for word. Dave says that might be the problem. I will check that out and come back to it. Possibly even bumping this thread. I've been working on this code off and on for a couple months now.
    christ!! thanks again. both of you!!
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  14. #14
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    You have a few choices:
    1) Declare value as a static array. This way the memory address remains valid even after the function returns.
    2) malloc() memory for word and then copy the string to it. Don't forget to free() the memory after using it in the calling function though.
    3) Make value a global variable. This is usually a discouraged work-around.
    4) Pass a buffer to the function in which to store the string. So you'd use the buffer passed to the function instead of the local word variable. This would be my preferred choice.
    starting from number one. are there anything else i have to do on declaring the array static. i have done the following
    Code:
     char names[MAXFIELDS][MAXFIELDS],temp[MAXFIELDS];
      static char values[MAXFIELDS][MAXFIELDS];
    however the code still crashes. are their changes to other functions i should be making?
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  15. #15
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Are you checking return values of getenv and such? Do you have the environment variables set? Using your code much like it is with the static values, and setting a couple environment variables, I get this.
    Code:
    http://cboard.cprogramming.com/online.php?order=asc&sort=username&pp=25&page=1
     using POST
    http://cboard.cprogramming.com/online.php?order = asc<br>sort = username<br>pp = 25<br>page = 1<br>Content-type: text/html
    
    <html>
    <head> <title> CGINCform</title> </head>
    <body bgcolor = "purple">
    <center> <h1>CGINC</h1> </center><br>
    http://cboard.cprogramming.com/online.php?order=asc
    sort=username
    pp=25
    page=1
    
    <br>http://cboard.cprogramming.com/online.php?order=asc
    sort=username
    pp=25
    page=1
    </body>
    </html>
    This is not to say I've checked everything, but before I added the environment variables, it was crashing.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 10
    Last Post: 09-04-2008, 01:27 PM
  2. Direct memory access?
    By _izua_ in forum Windows Programming
    Replies: 4
    Last Post: 08-01-2008, 02:08 AM
  3. Question regarding Memory Leak
    By clegs in forum C++ Programming
    Replies: 29
    Last Post: 12-07-2007, 01:57 AM
  4. Onboard video card memory access
    By HermioneFan in forum Game Programming
    Replies: 1
    Last Post: 05-28-2003, 09:53 AM
  5. Memory Access Error when using Strcpy()
    By fgs3124 in forum C Programming
    Replies: 2
    Last Post: 03-15-2002, 03:07 PM