Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Some explanation please on a small program ?

Hello I post a code that illustrate something I don't understand.
See explanations bellow.

class A
{
public:
A(){ ptr[0] = (char **) calloc(100, sizeof(char*)); } // reserve 100 slots

~A(){
printf("destructor\n");
for ( int idx = 0; idx < 100; ++idx )
printf("ptr[0][%d] = %x\n", idx, ptr[0][idx] );
ptr[0][0] = 0;
ptr[0][1] = 0;
for ( int idx = 0; idx < 100; ++idx )
printf("ptr[0][%d] = %x\n", idx, ptr[0][idx] );
free( ptr[0] ); // core dump !
}

char empty[300];
char** ptr[10];
int empty2[320];
};

int main() {

char * string1 = (char *) malloc( 6 * sizeof(char) );
char * string2 = (char *) malloc( 6 * sizeof(char) );

{
A a;

// some string
memcpy ( string1, "Hello", 6 );
memcpy ( string2, "World", 6 );
a.ptr[0][0]= &string1[3];
a.ptr[0][1]= &string2[1];

printf("<%s>\n", a.ptr[0][0] );
printf("<%s>\n", a.ptr[0][1] );

// here we overlap string1, but volontary over sized too
memcpy(a.ptr[0][0], "tes laitues sechent-elles ?", 28 );

printf("<%s>\n", string1 );
printf("<%s>\n", a.ptr[0][0] );

} // here core dump after destructor call

// free(string1);
// free(string2);

// exit(0);
}

A memory overdump is generated here :
memcpy(a.ptr[0][0], "tes laitues sechent-elles ?", 28 );
If this line is commented out the program runs well.

As you can see in the destructor, pointers ptr[0][0] and ptr[0][1] are forced to zero. So I would like to understand why the program crash on the free() in the destructor ! It's like if it's trying to free the ressource of string1 that can't be adressed anymore.
This is the backtrack :
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7d19770 in raise () from /lib/tls/i686/cmov/libc.so.6
#2 0xb7d1aef3 in abort () from /lib/tls/i686/cmov/libc.so.6
#3 0xb7d4ed0b in __fsetlocking () from /lib/tls/i686/cmov/libc.so.6
#4 0xb7d568bd in mallopt () from /lib/tls/i686/cmov/libc.so.6
#5 0xb7d56a44 in free () from /lib/tls/i686/cmov/libc.so.6
#6 0x080489c0 in ~A (this=0xbfa020e8) at test2.cpp:21
#7 0x08048878 in main () at test2.cpp:52

Thank you.
-Sebastien.F
[2590 byte] By [Seb256] at [2007-11-11 10:30:18]
# 1 Re: Some explanation please on a small program ?
ptr[0][0] = 0;
ptr[0][1] = 0;

where are you allocating for them? you need to allocate for ptr , then ptr[i]
it career at 2007-11-11 20:58:42 >
# 2 Re: Some explanation please on a small program ?
There are set here :

a.ptr[0][0]= &string1[3];
a.ptr[0][1]= &string2[1];

and string1 and string2 are already allocated above.

The thing is when I comment out the memcpy() it is ok.
Seb256 at 2007-11-11 20:59:42 >
# 3 Re: Some explanation please on a small program ?
use sprintf and not memcpy. Your day will be much much better! And, overlapped memory regions should use memmove instead, if that is what you meant when you said they were overlapped.
jonnin at 2007-11-11 21:00:45 >
# 4 Re: Some explanation please on a small program ?
I have replaced all my memcpy by sprintf like this :

//memcpy ( string1, "Hello", 6 );
sprintf( string1, "Hello");
//memcpy ( string2, "World", 6 );
sprintf ( string2, "World");
and
//memcpy(a.ptr[0], "tes laitues sechent-elles ?", 28 );
sprintf(a.ptr[0], "tes laitues sechent-elles ?" );

But still the same problem !
Seb256 at 2007-11-11 21:01:40 >
# 5 Re: Some explanation please on a small program ?
Actually, free() expects ptr[0][0] or something of that sort. You have a pointer to pointer to pointer, and free expect only a pointer, so you need two levels of dereferencing. Why not use a vector of strings and be rid of all the pointer mess?
Danny at 2007-11-11 21:02:40 >
# 6 Re: Some explanation please on a small program ?
I have simplify the code that should brings the same problems:
it is "C" now.
int main() {

char * string1 = (char *) malloc( 6 * sizeof(char) );
char * string2 = (char *) malloc( 6 * sizeof(char) );

char ** ptr = (char **) calloc(100, sizeof(char*)); // reserve 100 slots
for ( int idx = 0; idx < 100; ++idx )
printf("ptr[%d] = %x\n", idx, ptr[idx] );

sprintf( string1, "Hello");
//memcpy ( string2, "World", 6 ); // idem que le sprintf
sprintf ( string2, "World");

ptr[0]= &string1[3];
ptr[1]= &string2[1];

// print result
printf("<%s>\n", ptr[0] );
printf("<%s>\n", ptr[1] );

// here we overlap string1, but volontary over sized too
//memcpy(ptr[0], "tes laitues sechent-elles ?", 28 );
sprintf(ptr[0], "tes laitues sechent-elles ?" );
//memcpy(ptr[0], "hilll", 6 );

// print result
printf("<%s>\n", string1 );
printf("<%s>\n", ptr[0] );

// print
for ( int idx = 0; idx < 100; ++idx )
printf("ptr[%d] = %x\n", idx, ptr[idx] );

ptr[0] = 0;
ptr[1] = 0;

// print
for ( int idx = 0; idx < 100; ++idx )
printf("ptr[%d] = %x\n", idx, ptr[idx] );

free( ptr ); // core dump !
printf("End\n");

}

And I think It is crashing because when we override the memory allocated we lose the size information of the C tables store somewhere.

I can't refactor the code with STL container (even I would like) because of restricted time ... for this project where we face memory leaks/
Remember that this code is for illustration the real product is bigger and complex.
Thank you.
Seb256 at 2007-11-11 21:03:44 >
# 7 Re: Some explanation please on a small program ?
well the problem is your memory is messed up somehow, the memcpy or sprintf or whatever is all the same really (sprintf is just safer and easier to read / the reader knows your doing string stuff now). I do not see where your memory is allocated for the second dimension.

you need

char ** cp2d;
cp2d = new char*[somesize];
for(x=0; x <somesize; x++)
cp2d[x] = new char[othersize];
...

sprintf(cp2d[0],"%s", "there we go");
etc..

swap new for malloc or calloc or whatever your favorite is.

yes, you *can* do it all in a single statement, if you can figure out the syntax, but its harder to maintain when you do this.
jonnin at 2007-11-11 21:04:43 >