Thread: string changing problem

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    4

    string changing problem

    Hello everyone.
    Im playing with one parser that is not working.
    It's failing with segment.error, and I could not fix it, since im not good at all in c .
    I think the issue is in one place, where im trying to change one string to other one. It's always failing on third step - ending with that segm.error.
    Im calling fillcd, where cid2cid "function" is used to modify the buf string.
    After third succesfully changed string it fails…Isnt there a memory problem?

    buf: 3000/000/00/MOY,3000/000/00/MAX,3000/000/00/CUM,3000/000/00/ECH,3004/000/00/CUM,3004/000/00/ECH,3004/000/00/MOY,3004/000/00/MAX,3004/001/00/CUM,3004/001/00/ECH,3004/001/00/MOY,3004/001/00/MAX,3008/000/00/CUM,3008/000/00/ECH,3008/000/00/MOY

    Output in cd variable should be like: MOY_3000_000_00,MAX_3000_000_00,CUM_3000_000_00, ….

    Thanks for any ideas !

    Script:

    Code:
    ...
    char *cid2cid(char *s){
      static char tmp[20];
          
      strcpy(tmp, s);
      s[0]=tmp[12]; 
      s[1]=tmp[13];
      s[2]=tmp[14];
      s[3]='_';
      s[4]=tmp[0];
      s[5]=tmp[1];
      s[6]=tmp[2];
      s[7]=tmp[3];
      s[8]='_';
      s[9]=tmp[5];
      s[10]=tmp[6];
      s[11]=tmp[7];
      s[12]='_';
      s[13]=tmp[9];
      s[14]=tmp[10];
      s[15]='\0';
      return s;
    }
    
    int fillcd( char *buf, char *cd[], FILE *f ) {
      char *p;
      int i;  
      cd[0]=cid2cid(strdup(strtok(buf,",")));
      i=1;
      while ( (p=strtok(NULL, ",")) != NULL ) cd[i++]=strdup(cid2cid(p));
      cd[i]=strdup("FINITO");
      return i;
    }
    
    …
    
    char buf[1000], classn[100], *procstr[100], *cd[200];
    counters=fillcd(inbuf,cd, fout);
    Thanks for any ideas !
    Last edited by dusoo; 04-21-2008 at 01:03 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    The string you're making longer is the result of a call to strdup().
    Which will (as far as you can assume) will only store as many characters as originally stored.
    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.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    4
    hi, but im not creating the string longer. Im just changing positions of some letters.
    from original string 3000/000/00/MOY - i get MOY_3000_000_00, what's same length. Can u please advice me what to change? ..since im totally new to c... Thanks.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Perhaps
    1. Validate your data before assuming that the format is correct.
    2. Add a condition to your while loop which limits the range of i to be that of the array.

    > int fillcd( char *buf, char *cd[], FILE *f )
    You don't use f in this function.
    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.

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    Hello,

    I tried the following code:

    Code:
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    ...the two functions cid2cid and fillcd (I just added a printf() in the fillcd loop)...
    
    int main(int c,char** p) {
      char b[]="3000/000/00/MOY,3000/00[.......]";
      char* cd[1024];
      fillcd(b,cd);
      return 0;
    }
    And it seems to work:

    tmp - gcc foo.c -o foo
    tmp - ./foo
    2: MAX_3000_000_00
    3: CUM_3000_000_00
    4: ECH_3000_000_00
    5: CUM_3004_000_00
    6: ECH_3004_000_00
    7: MOY_3004_000_00
    8: MAX_3004_000_00
    9: CUM_3004_001_00
    10: ECH_3004_001_00
    11: MOY_3004_001_00
    12: MAX_3004_001_00
    13: CUM_3008_000_00
    14: ECH_3008_000_00
    15: MOY_3008_000_00

    _however_ you do get a segv if you declare b as a 'char*' (depending on the system, the string is allocated in the static data segment and may not be modifiable in this case, which was the case for me)

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    4
    The strange thing about my error is, that few days ago it was running without problem with the same data. Now it is failing (no data change). On other system the same parser is working without problem...So i dont have a clue what's going on. Could be there a memory allocation problem? thanks

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by dusoo View Post
    The strange thing about my error is, that few days ago it was running without problem with the same data. Now it is failing (no data change). On other system the same parser is working without problem...So i dont have a clue what's going on. Could be there a memory allocation problem? thanks
    Did you understand the post by root4?

    There is a difference between:
    char *str = "something";
    and
    char str[] = "something";

    In the latter case, you can write to the original string because the string memory is actually inside str as an array, in the first one, you can't, because the string itself is stored in "read-only" memory. This DOES vary between compilers - but shouldn't make any difference which machine you run it on.

    Edit: Note that this line:
    Code:
     while ( (p=strtok(NULL, ",")) != NULL ) cd[i++]=strdup(cid2cid(p));
    first writes to p, the copies the resulting string.

    One solution to avoid all of that would be:
    Code:
    char *cid2cid(char *s){
      static char tmp[20];
          
      tmp[0]=s[12]; 
      tmp[1]=s[13];
      tmp[2]=s[14];
      tmp[3]='_';
      tmp[4]=s[0];
      tmp[5]=s[1];
      tmp[6]=s[2];
      tmp[7]=s[3];
      tmp[8]='_';
      tmp[9]=s[5];
      tmp[10]=s[6];
      tmp[11]=s[7];
      tmp[12]='_';
      tmp[13]=s[9];
      tmp[14]=s[10];
      tmp[15]='\0';
      return tmp;
    }
    It's ok to return tmp since tmp is static, so it doesn't go away when the function returns.
    [And the above code is a tiny bit faster, since it doesn't copy s into tmp first.]

    --
    Mats
    Last edited by matsp; 04-22-2008 at 02:57 AM.
    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.

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    4
    hi
    now i understand at least a bit the diff between those two
    char *str = "something"; and char str[] = "something";

    i have swaped your part of code with my, and it helped !

    thanks all for your time, now i just need to continue with learning c

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. OOP Question DB Access Wrapper Classes
    By digioz in forum C# Programming
    Replies: 2
    Last Post: 09-07-2008, 04:30 PM
  2. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  3. Replies: 8
    Last Post: 04-25-2008, 02:45 PM
  4. Custom String class gives problem with another prog.
    By I BLcK I in forum C++ Programming
    Replies: 1
    Last Post: 12-18-2006, 03:40 AM
  5. Something is wrong with this menu...
    By DarkViper in forum Windows Programming
    Replies: 2
    Last Post: 12-14-2002, 11:06 PM