segmentation fault - Modify a string repeatedly in C -


i want modify string this:—

mainstring="",            toupdate="abc" -> return# "abc=1" mainstring="abc=1",       toupdate="abc" -> return# "abc=2" mainstring="abc=2",       toupdate="abc" -> return# "abc=3" mainstring="abc=3",       toupdate="xyz" -> return# "abc=3:xyz=1" mainstring="abc=3:xyz=1", toupdate="xyz" -> return# "abc=3:xyz=2" mainstring="abc=3:xyz=2", toupdate="xyz" -> return# "abc=3:xyz=3" 

i have following function:

void updatestring(char *mainstring, char toupdate[20]) {     char *pdata[50][2];     char *saveptr1=null;     int i=0,j=0,nispresentflag=0;     unsigned int cdrcnt=1;     char workbuf1[200];     char workbuf[200];       memset(workbuf,0,200);     memset(workbuf1,0,200);      if(strlen(mainstring)>0)     {         strcat(mainstring,":");     }      strcpy(workbuf1,mainstring);      pdata[i][0]=strtok_r(workbuf1,"=",&saveptr1);     pdata[i][1]=strtok_r(null,":",&saveptr1);      if(pdata[i][0]) {i++;pdata[i][0]=null; pdata[i][1]=null;}      while((pdata[i][0]=strtok_r(null,"=",&saveptr1)))     {         pdata[i][1]=strtok_r(null,":",&saveptr1);         i++;     }      for(j=0;j<i;j++)         if(strncmp(toupdate,pdata[j][0],strlen(pdata[j][0]))==0)         {             cdrcnt=atoi(pdata[j][1]);             cdrcnt+=1;             sprintf(pdata[j][1],"%d",cdrcnt);             nispresentflag=1;             break;         }      if(nispresentflag==1)         for(j=0;j<i;j++)             sprintf(workbuf,"%s%s=%s:",workbuf,pdata[j][0],pdata[j][1]);     else         sprintf(workbuf,"%s%s=%d:",mainstring,toupdate,1);      workbuf[strlen(workbuf)-1]='\0';       memset(mainstring,0,200);     strcpy(mainstring,workbuf);  } 

curiously, function working, causing core dump segfault.

what wrong code? better way can manage above task?

==============================================================================

edit 1

string declaration:

char mainstring[200]; 

the call like:

updatestring((char*)&mainstring,"abc"); 

preliminary observation

given test code:

static void chkit(char *s, char *u) {     printf("[%s] && [%s]", s, u);     updatestring(s, u);     printf(" ==> [%s]\n", s); }  int main(void) {     char mainstring[200] = "";      chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "xyz");     chkit(mainstring, "xyz");     chkit(mainstring, "xyz");     chkit(mainstring, "def");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "xyz");     chkit(mainstring, "abc");     chkit(mainstring, "ghi");     return 0; } 

the output is:

[] && [abc] ==> [abc=1] [abc=1] && [abc] ==> [abc=2] [abc=2] && [abc] ==> [abc=3] [abc=3] && [xyz] ==> [abc=3:xyz=1] [abc=3:xyz=1] && [xyz] ==> [abc=3:xyz=2] [abc=3:xyz=2] && [xyz] ==> [abc=3:xyz=3] [abc=3:xyz=3] && [def] ==> [abc=3:xyz=3:def=1] [abc=3:xyz=3:def=1] && [abc] ==> [abc=4:xyz=3:def=1] [abc=4:xyz=3:def=1] && [abc] ==> [abc=5:xyz=3:def=1] [abc=5:xyz=3:def=1] && [abc] ==> [abc=6:xyz=3:def=1] [abc=6:xyz=3:def=1] && [abc] ==> [abc=7:xyz=3:def=1] [abc=7:xyz=3:def=1] && [abc] ==> [abc=8:xyz=3:def=1] [abc=8:xyz=3:def=1] && [abc] ==> [abc=9:xyz=3:def=1] [abc=9:xyz=3:def=1] && [abc] ==> [abc=10:=3:def=1] [abc=10:=3:def=1] && [xyz] ==> [abc=10:=3:def=1:xyz=1] [abc=10:=3:def=1:xyz=1] && [abc] ==> [abc=11:3:def=1:xyz=1] [abc=11:3:def=1:xyz=1] && [ghi] ==> [abc=11:3:def=1:xyz=1:ghi=1] 

there's problem when numbers increase 1 digit 2 digits.

one problem

in code:

if (nispresentflag == 1)     (j = 0; j < i; j++)         sprintf(workbuf, "%s%s=%s:", workbuf, pdata[j][0], pdata[j][1]); 

you invoking undefined behaviour writing workbuf , passing 1 of parameters. dangerous. there's moderate chance you'll away it, 'get away' operative term — there's no guarantee work.

the overwrite problem occurs when format new number insufficient space.

working code

the code below seems work:

#include <string.h> #include <stdio.h> #include <stdlib.h>  static void updatestring(char *mainstring, char toupdate[20]) {     char *pdata[50][2];     char *saveptr1 = null;     int   = 0;     int   nispresentflag = 0;     char  workbuf1[200];     char  workbuf[200];     char  extra[16];      if (strlen(mainstring) > 0)         strcat(mainstring, ":");      strcpy(workbuf1, mainstring);      pdata[i][0] = strtok_r(workbuf1, "=", &saveptr1);     pdata[i][1] = strtok_r(null, ":", &saveptr1);      if (pdata[i][0])         i++;      while ((pdata[i][0] = strtok_r(null, "=", &saveptr1)) != 0)     {         pdata[i][1] = strtok_r(null, ":", &saveptr1);         i++;     }      (int j = 0; j < i; j++)     {         if (strncmp(toupdate, pdata[j][0], strlen(pdata[j][0])) == 0)         {             unsigned int cdrcnt = atoi(pdata[j][1]);             cdrcnt += 1;             pdata[j][1] = extra;             sprintf(pdata[j][1], "%u", cdrcnt);             nispresentflag = 1;             break;         }     }      if (nispresentflag == 1)     {         char *dst = workbuf;         (int j = 0; j < i; j++)         {             int n = sprintf(dst, "%s=%s:", pdata[j][0], pdata[j][1]);             /* broken if sprintf() returns -1 */             dst += n;         }     }     else         sprintf(workbuf, "%s%s=%d:", mainstring, toupdate, 1);      workbuf[strlen(workbuf)-1] = '\0';      strcpy(mainstring, workbuf); }  static void chkit(char *s, char *u) {     printf("[%s] && [%s]", s, u);     updatestring(s, u);     printf(" ==> [%s]\n", s); }  int main(void) {     char mainstring[200] = "";      chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "xyz");     chkit(mainstring, "xyz");     chkit(mainstring, "xyz");     chkit(mainstring, "def");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "abc");     chkit(mainstring, "xyz");     chkit(mainstring, "abc");     chkit(mainstring, "ghi");     chkit(mainstring, "pqrstu");     chkit(mainstring, "i");     chkit(mainstring, "i");     chkit(mainstring, "i");     chkit(mainstring, "pqrstu");      return 0; } 

it leaves out memset() operations; null terminated string can copied on arbitrary data , long don't go looking beyond null terminator, won't have problems. variable extra used store new number; avoids problems when number changes n n+1 digits. function sprintf() returns number of characters wrote; used add data work buffer safely.

example output

[] && [abc] ==> [abc=1] [abc=1] && [abc] ==> [abc=2] [abc=2] && [abc] ==> [abc=3] [abc=3] && [xyz] ==> [abc=3:xyz=1] [abc=3:xyz=1] && [xyz] ==> [abc=3:xyz=2] [abc=3:xyz=2] && [xyz] ==> [abc=3:xyz=3] [abc=3:xyz=3] && [def] ==> [abc=3:xyz=3:def=1] [abc=3:xyz=3:def=1] && [abc] ==> [abc=4:xyz=3:def=1] [abc=4:xyz=3:def=1] && [abc] ==> [abc=5:xyz=3:def=1] [abc=5:xyz=3:def=1] && [abc] ==> [abc=6:xyz=3:def=1] [abc=6:xyz=3:def=1] && [abc] ==> [abc=7:xyz=3:def=1] [abc=7:xyz=3:def=1] && [abc] ==> [abc=8:xyz=3:def=1] [abc=8:xyz=3:def=1] && [abc] ==> [abc=9:xyz=3:def=1] [abc=9:xyz=3:def=1] && [abc] ==> [abc=10:xyz=3:def=1] [abc=10:xyz=3:def=1] && [xyz] ==> [abc=10:xyz=4:def=1] [abc=10:xyz=4:def=1] && [abc] ==> [abc=11:xyz=4:def=1] [abc=11:xyz=4:def=1] && [ghi] ==> [abc=11:xyz=4:def=1:ghi=1] [abc=11:xyz=4:def=1:ghi=1] && [pqrstu] ==> [abc=11:xyz=4:def=1:ghi=1:pqrstu=1] [abc=11:xyz=4:def=1:ghi=1:pqrstu=1] && [i] ==> [abc=11:xyz=4:def=1:ghi=1:pqrstu=1:i=1] [abc=11:xyz=4:def=1:ghi=1:pqrstu=1:i=1] && [i] ==> [abc=11:xyz=4:def=1:ghi=1:pqrstu=1:i=2] [abc=11:xyz=4:def=1:ghi=1:pqrstu=1:i=2] && [i] ==> [abc=11:xyz=4:def=1:ghi=1:pqrstu=1:i=3] [abc=11:xyz=4:def=1:ghi=1:pqrstu=1:i=3] && [pqrstu] ==> [abc=11:xyz=4:def=1:ghi=1:pqrstu=2:i=3] 

i did basic checking valgrind (and added dynamic memory allocation) , came clean bill of health.

note style of diagnostic printing. shows inputs , output, helpful. , encloses strings in distinctive marker (here []) stray spaces etc can spotted more easily.


Comments