Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Char array vs char pointer 1

Status
Not open for further replies.

dickiebird

Programmer
Feb 14, 2002
758
GB
With the following code fragment, if I run the program as below , I get a Segmentation fault at the sprintf
But if I redefine cmdline as an array, instead of char * , it works OK
Why ????
Its me and pointers again, isn't it ?!?!?!


main(argc, argv)
int argc;
char **argv;
{
char *cmdline;
/* char cmdline[50]; */
struct msqid_ds buf;
int quiet, ok, error;
quiet = ((argc > 3) && (argv[3][1]=='q'));
strcpy(argv0, argv[0]);
ok = 1;
if(!quiet)
{
fprintf(stderr, "%s\n\n", "Running ....");
fflush(stderr);
if(!ok)
exit(-255);
}

if ( argc == 1 )
{
/* Exec master server in background */
sprintf(cmdline, "%s %d %d -q&", argv[0], CIMASTER, CIMASTER );
}

Your help and guidance is much appreciated
;-)
Dickie Bird
db@dickiebird.freeserve.co.uk
 
Hello,

When you define a pointer variable
char *myPtr;
the compiler allocate just enough memory (generally 4 bytes) to store the address of some data. No other allocation is done.
Furthemore, if you do not initialize a non global pointer it contains a garbage value i.e. a random address in memory. This means that when you access the data pointed by your pointer you read or write at a random place in memory.
Before dereferencing a pointer (using the * or [] operator like this *myPtr or myPtr[0] which are the same thing) you should always be sure that the pointer has been given the address of valid data:
myPtr = /* some valid address like result of malloc or address of an array */

When you define an array variable
char myArray[50];
the compiler allocate enough memory for all the data of the array (here 50 bytes) and will replace each following occurence of the variable name by the address of these data.

Note: It is why an array variable can not be changed: it is not a memory location where the adress of data is stored like a pointer variable, it IS the address of the data. You can only change the data in the array.
myArray[0] = 'A'; /* OK */
myArray = malloc(60); /* Error myArray is not an lvalue */
myArray++; /* Error myArray is not an lvalue */

End of note.

In your code you define a pointer without giving it any value so it points to a random location.
The call to sprintf write the formatted string to the memory location pointed by its first argument. So in your case at a random place resulting in a Segmentation Fault because this random location is not readable or writable.
And you are lucky. Should this random location be writable you will not have the Segmentation violation but you will be erasing random data of your program. This kind of bug (memory corruption) is one of the more difficult to find.

When you define an array, the call to sprintf write the formatted string to the memory location pointed by its first argument. In your case the allocated 50 bytes.
Just be sure that the formatted string will not be longer than 50 bytes (counting the terminating '\0' char).

So, if you really want to use pointer be sure to give them a valid value before reading or writing to the pointed data.

char *cmdline = malloc(50);
...
sprintf(cmdline, ...);
...
free(cmdline);


And if you do not want to alloc and free small memory but still be able to parse your data with something like *ptr++, create a array and a pointer to this array:

char data[50];
char *cmdline = &(array[0]); /* or just '= array;' */
...
while (*cmdline++ != '\0') { ... }
...


Is it any clearer ?
 
Cheers dchoulette
Your reply dovetails well with the answers to a previous query submitted by me a month ago.
I will get the hang of C before I retire !
;-) Dickie Bird
db@dickiebird.freeserve.co.uk
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top