Here comes Thomas !!
Welcome ..... :)
Thomas has patched the question in all possible scenarios. He is right
..... one should make sure that one doesn't alter the contents of the
read-only portions of memory. Normally 'constants' used in the program
contribute towards the read-only portions.
Using memmove() will surely eliminate use of dynamic allocation and one
may move the contents within the same memory-pool, thus making the
implementation faster.
Thomas Hruska wrote:
> Roberto wrote:
>
>> I wrote the following code to trim a char string at left. The code is
>> simple and I think there is no error, but when I run, I get
>> a "Segmentation fault". If I use the debugger (gdb), the error does
>> not occur. May anyone help me to understand why? and where is the
>> error?
>> Thanks a lot.
>> I am using a Red Hat distribution, version 7.3 and a cc release,
>> version 2.96.
>> == code start (ltrim.c) ==
>> #include <errno.h>
>> #include <string.h>
>> /* ltrim() function
>> * parameters:
>> * string = the string to trim at left
>> * return value:
>> * char* : the trimmed string at left
>> */
>> char* ltrim(char *strn ){
>> if (strn!=NULL) {
>> char *p=strn;
>> char *tmp_buffer = NULL;
>> int l = strlen(p);
>> printf( "ltrim() : [%p] [%s], len: %d \n", p, p, l);
>>
>> tmp_buffer = (char*) calloc( l+1, sizeof(char) );
>> if (tmp_buffer!=NULL) {
>> int x=0;
>> char c='\0';
>> printf("buffer before the filling: [%p] [%s] [%d]\n",
>> tmp_buffer, tmp_buffer, strlen(tmp_buffer) );
>> strcpy( tmp_buffer, p );
>> printf("buffer after the filling with the string: [%p] [%s] [%d]
>> \n", tmp_buffer, tmp_buffer, strlen(tmp_buffer) );
>> while ( (c=tmp_buffer[x++])!=0 && c==' ' ) {
>> printf("p: %d, c: [%c] 0X%2X\n",x, c, c);
>> }
>> printf( "reset string [%p], len: %d to 0\n", p, l );
>> memset((void*)p, 0, l );
>> printf("prepare the return parameter\n");
>> strcpy(p, &tmp_buffer[x-1]);
>> printf( "new string: [%s] l: %d -> free memory : [%p] [%s] [%d]
>> \n", p, strlen(p), tmp_buffer, tmp_buffer, strlen(tmp_buffer) );
>> free(tmp_buffer);
>> tmp_buffer = NULL;
>> printf( "memory freed\n");
>> printf( "ltrim() : (trimmed) [%s], len: %d \n", strn, strlen
>> (strn) );printf( "ltrim() : (trimmed) [%s], len: %d \n", strn, strlen
>> (strn) );
>> } else {
>> printf( "ltrim() : cannot allocate memory [%s] \n", strerror
>> (errno));
>> }
>> }
>> printf("return the value\n");
>> return (char*) strn;
>> }
>> int main (char **argz, char argc)
>> {
>> char *s0 = " bye 1 ";
>> char *d0 = ltrim(s0);
>> printf( "before: [%s] after [%s] \n", s0, d0 );
>> exit(0);
>> }
>> == code end ====
>>
>
> Seeing as no one has actually provided a solution to the problem, I'll
> reply.
>
> 1) You have a bunch of printf()'s in your code. Let's take those out.
>
> > char* ltrim(char *strn ){
> > if (strn!=NULL) {
> > char *p=strn;
> > char *tmp_buffer;
> > int l = strlen(p);
> >
> > tmp_buffer = (char*) calloc( l+1, sizeof(char) );
> > if (tmp_buffer!=NULL) {
> > int x=0;
> > char c='\0';
> > strcpy( tmp_buffer, p );
> > while ( (c=tmp_buffer[x++])!=0 && c==' ' ) {
> > }
> > memset((void*)p, 0, l );
> > strcpy(p, &tmp_buffer[x-1]);
> > free(tmp_buffer);
> > } else {
> > printf( "ltrim() : cannot allocate memory [%s] \n", strerror
> > (errno));
> > }
> > }
> >
> > return (char*) strn;
> > }
>
> 2) Crash probably occurs on the line with the strcpy(). This is
> because only 2 bytes are allocated to tmp_buffer and p is an identical
> pointer to the input string...which is more than two bytes.
>
> 3) This is a poorly implemented ltrim() function, IMO. You seem to
> want to inline edit the string. You have no way of knowing if the
> memory you are accessing to edit is in a static data segment (i.e.
> read-only) or not. But it is odd that you are allocating memory for an
> inline operation. Make up your mind.
>
> 4) Consider using Safe C++ - BString already has a fully-functional and
> debugged LTrim() member. Or at least switch to C++.
>
> 5) If you insist on using C and inline editing, learn how to use
> memmove() and drop all the dynamic allocation calls.
>
>