1

here i am dynamically allocating memory to p so that i can change a particular character of a string, but this code hangs in the middle

 int main()
 {
  char *p;
  p=malloc(10*sizeof(char));
  p="string";
  p[0]='d';
  printf("%s",p);
 }

i tried replacing p="string" at line no 5 with strcpy(p, "string") and the code worked perfectly.can anyone tell me the reason behind this.

 int main()
 {
   char *p;
   p=malloc(10*sizeof(char));
   strcpy(p, "string");
   p[0]='d';
   printf("%s",p);
 }
simonc
  • 41,632
  • 12
  • 85
  • 103
himmi
  • 19
  • 4
  • 1
    Others have answered your main question but I'll just add that there's never any point in including `sizeof(char)` in your code - `sizeof(char)` is 1 by definition, regardless of how many bits in a char on your system. – Vicky Jan 31 '13 at 17:01

5 Answers5

2

A pointer can either own a resource (malloc) or point a resource already owned by another entity. When you do p="string";, you are creating a const char * to which you assign the character pointer p, there by leaking the malloc'd memory in the previous line, in the latter, you're just replacing the contents inside the malloc'd memory; former is a bug/issue, latter is not. It is to be noted that although it's bad practise to leak resources/memory, it isn't the reason behind the hang.

The reason you get a hang is because the edit you make in your C code under the hood tries to edit you're program's read-only memory space (const char * variables are created as immutable byte arrays in this segment of the program memory). when does c++ allocate/deallocate string literals explains further on this.

As for passing the required bytes to malloc, a good practise to avoid using type in the expression:

const size_t count_required = 10;
char *p = malloc(sizeof(*p) * count_required);
// changing p's type to int* would also work without editing the malloc argument

when the type of p is changed to, say, float, int or any other type the expression will continue to work fine without any changes.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
1

The line

 p="string";

changes p to point to a read-only string literal, leaking the previously allocated memory in the process. You can't write to a string literal so p[0]='d'; will likely cause a seg fault.

Your second version, uses

strcpy(p, "string");

to copy a the contents of read-only string literal into the memory you previously allocated. You're still using the buffer you dynamically allocated here so are safe to change its contents in later code.

One other very minor point, sizeof(char) is guaranteed to be 1 so you can simplify your malloc call to

 p=malloc(10);
simonc
  • 41,632
  • 12
  • 85
  • 103
  • 1
    @Shark Why? Can you point to some systems where that isn't the case? The C89 standard *3.3.3.4 The sizeof operator* certainly states that `sizeof(char)==1` – simonc Jan 31 '13 at 17:02
  • Using sizeof(char) instead of 1 will however make the code truly cross platform. – Keith Miller Jan 31 '13 at 17:31
  • 2
    @simonc By definition, `sizeof` returns the size of the operand in units of `char`. So it is guaranteed to be 1. No problem there. – Daniel Fischer Jan 31 '13 at 17:39
  • There is a huge yet subtle difference between `malloc(10)` and `malloc(9*sizeof(char) + 1)` – Shark Feb 05 '13 at 15:43
1

Strings are not values, in C. You cannot copy strings around using assignment (=), but you can assign pointers (pointers are "real" values).

To copy a string into your newly allocated memory, you need:

strcpy(p, "string");

The way you've written it, you are overwriting the pointer returned by malloc() with the address of a static string constant. This causes a memory leak; avoiding them is one of the challenges that makes C such a rewarding language to program in.

unwind
  • 391,730
  • 64
  • 469
  • 606
0

firstly, there is a memory leak in your first program. You malloc and then assign the pointer to another constant string.

Secondly, in the first program, you're modifying a CONSTANT string. but the second "CORRECT" program, you're duplicating that constant string and copying it into the memory allocated. Which, you're free to change.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
0

char amessage[] = "now is the time"; /* an array */

char *pmessage = "now is the time"; /* a pointer */

"amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessagewill always refer to the samestorage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents."

courtsey K&R

marko
  • 9,029
  • 4
  • 30
  • 46
abhi
  • 71
  • 1
  • 1
  • 5