LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   segfault caused depending on how a function is called (http://www.linuxquestions.org/questions/programming-9/segfault-caused-depending-on-how-a-function-is-called-543316/)

emge1 04-04-2007 11:36 AM

segfault caused depending on how a function is called
 
I have this function to trim whitespace which it segfaults
if i call it this way:
Code:

  /*bad*/
  btrimws("  a\n");

or this way:
Code:

  /*bad*/
  char *str1="  b\n";
  btrimws(str1);

but not this way:
Code:

  /*works ok*/
  char *str2= (char *)malloc(10);
  strcpy(str2,"  c\n");
  btrimws(str2);

or this way:
Code:

  /*works ok*/
  char str3[]= "  d\n";
  btrimws(str3);

what should i do? I think i know its segfaulting because I am trying to write over something that hasn't been allocated, but I am not 100% sure. Also I don't understand why or not quite sure what I can check for in my trim function to make it work for all cases.

thanks a lot in advance.




Code:

#define BLOCK_COPY(D,S,L)        { if ((L) > 0) memmove ((D),(S),(L)); }
#define WSPACE(c)                (isspace ((unsigned char) c))

int btrimws (char* b) {
  int i, j;
  if (b == NULL) return -1;
  int slen = strlen(b);
  if(slen <= 0) return -1;

  for (i = slen - 1; i >= 0; i--) {
      if (!WSPACE (b[i])) {
        if (b[i+1] != (unsigned char) '\0')
            b[i+1] = (unsigned char) '\0';      /* segfaults here*/
        for (j = 0; WSPACE(b[j]); j++) {}
        return bdelete (b, 0, j);
      }
  }
  b[0] = (unsigned char) '\0';
  slen = 0;
  return 0;
}

*note: this code is modified from the The Better String Library

emge1 04-04-2007 11:37 AM

here is the other function that gets called from the trim function.

Code:

/*  int bdelete (char* b, int pos, int len)
 *
 *  Removes characters from pos to pos+len-1 inclusive and shifts the tail of
 *  the char* starting from pos+len to pos.  len must be positive for this
 *  call to have any effect.  The section of the string described by (pos,
 *  len) is clamped to boundaries of the char* b.
 */
int bdelete (char* b, int pos, int len) {
  /* Clamp to left side of bstring */
  if (pos < 0) {
      len += pos;
      pos = 0;
  }
  int slen = strlen(b);
  if (len < 0 || b == NULL || slen < 0 )
      return -1;
  if (len > 0 && pos < slen) {
      if (pos + len >= slen) {
        slen = pos;
      } else {
        BLOCK_COPY ((char *) (b + pos),
                    (char *) (b + pos + len),
                    slen - (pos+len));
        slen -= len;
      }
      b[slen] = (unsigned char) '\0';
  }
  return 0;
}


xhi 04-04-2007 11:48 AM

you cant modify a string literal.

graemef 04-04-2007 12:26 PM

Quote:

Originally Posted by xhi
you cant modify a string literal.

So if you want it to work with literals then you need to change the signature of the function.Maybe a function that accepts a character array and returns the modified character array is what you want.

Code:

char * trim (const char *)

xhi 04-04-2007 12:48 PM

Quote:

Originally Posted by graemef
So if you want it to work with literals then you need to change the signature of the function.Maybe a function that accepts a character array and returns the modified character array is what you want.

Code:

char * trim (const char *)

i agree.. and another option would be a function that requires the return memory to be passed to the function.. allowing the return to notify of success..

ie
Code:

int trim(const char* input, char* output);
avoiding calls to malloc, this could be used as such
Code:

char buffer[STR_MAX];
if(!trim("    First char is F", buffer)
  printf("error trimming");

or something like that anyhow

kaz2100 04-04-2007 03:40 PM

Hya,

In the old days, --fwritable-stings or something used to take care of this issue.

Happy Penguins!

xhi 04-04-2007 03:48 PM

Quote:

Originally Posted by kaz2100
Hya,

In the old days, --fwritable-stings or something used to take care of this issue.

Happy Penguins!

that sounds like pure evil


All times are GMT -5. The time now is 02:01 PM.