0

I am playing with array and pointer and got this segmentation fault. Can any one explain why I have been getting this segmentation fault in this code when I move my pointer "p" below "ptr" pointer in the code and when I comment out one of printf statement alternatively it disappears:

 typedef struct str{
   char* ptr;
  }str_t;

copy(str_t t){
   char a[12];
   char *p;   //  <------ no error when move below ptr pointer 
   char *ptr;

   printf("t= %s p = %d ptr = %d\n", t, p, ptr);

   strcpy(a, t.ptr);
   printf("a = %s %u\n", a, &a);

   strcpy(ptr, t.ptr);
   printf("ptr = %s %u\n", ptr, &ptr); //<--- comment it error disappears

   p= t.ptr;
   printf("p = %s %u",p, &p);  //<--- comment it error disappears
 }

int main ()
{
  str_t t;
  char app[] = "hello";
  char ap[] ="world";

  t.ptr = ap;
  copy(t);

  printf("%s\n", app);

  return 0;
}

you can compile the code here to see the result : http://codepad.org/Q7zS8NaC

Thank you , for visiting this question .

2
  • 1
    The strcpy(ptr, t.ptr) is copying t.ptr to the location given by ptr which hasn't been initializing. This results in undefined behavior which can be changed just by re-arranging code. If rearranging code makes a problem go away, that doesn't mean you don't have a problem. :) Commented Oct 18, 2013 at 3:12
  • You would do well to read about malloc(), free(), and strdup(). Commented Oct 18, 2013 at 3:15

2 Answers 2

5

strcpy doesn't allocate space at the pointer, p, to store the string. You need to declare it as an array or allocate space with malloc or calloc.

Try this:

 int len = strlen (t.ptr);         // find length of string

 char * ptr = calloc (len + 1, 1); // allocate space for ptr
 if (!ptr) return;                 // error check calloc
 strcpy (ptr, t.ptr);              // copy the string

 char * p = calloc (len + 1, 1);   // do the same thing for p
 if (!p) return;
 strcpy (p, t.ptr);

That will fix your segmentation fault.

You have a couple of more errors though, which are mainly format issues.

  1. %u prints an unsigned integer. It looks like you're trying to print a pointer, so use %p instead.
  2. printf("t= %s p = %d ptr = %d\n", t, p, ptr); is totally wrong.
    1. You need to reference the member of t, which is t.ptr
    2. p is a pointer, not an integer. Use %p instead of %d
    3. ptr is also a pointer. Use either %p or %s

Read the documentation of printf if you're ever unsure about formatting. In fact, read the documentation of any function, if you are unsure how to use it - you'll save yourself a lot of headaches.

Sign up to request clarification or add additional context in comments.

2 Comments

certainly . Thank you as well for explanation . Just one point I was not trying strcpy on p , just wanted it to point to the struct element.:)
@SelectCall okay, all you need to do is ptr = t.ptr;
2

Your code has several undefined behaviors:

  • The first printf prints a pointer using %d specifier
  • The second call of strcpy call attempts to write to memory pointed to by an uninitialized pointer
  • The second and third calls of printf passes a pointer to an array to a format specifier %u

Removing one of the pointers makes the code not crash, but since undefined behavior is there, the code does not work correctly, and may crash at any time.

Here is one way of fixing it:

char a[12];
char *p;
char *ptr;

printf("t= %s p = %x ptr = %x\n", t.ptr, (void*)p, (void*)ptr);

strcpy(a, t.ptr);
printf("a = %s %x\n", a, (void*)(&a[0]));
ptr = malloc(strlen(t.ptr)+1);
// In production, check ptr for NULL
strcpy(ptr, t.ptr);
printf("ptr = %s %x\n", ptr, (void*)&ptr);

p= t.ptr;
printf("p = %s %x", p, (void*)&p);
// Release the memory when you are done
free(ptr);

4 Comments

Okay I understand it was not having memory allocation before however what I did't understand when I move the char* p above the char* ptr it crashes , both of these pointer were not initialized I wonder what happened by just move char* p above char* ptr. btw thank you for explaning
@SelectCall When you reference uninitialized memory, you read leftovers from whomever has been using that particular address before you. Unititialized pointer points to some place in memory by virtue of having a value. This may be space allocated to your program (very often, something close to its stack) or space not allocated to your program. In the first case the program will "run" without crashing; in the second case, it will definitely crash. It usually better for your program to crash than to spend time chasing random errors. Use valgrind to find memory errors without waiting for a crash.
Let me consider it as correct and for an instance memeory was allocated to the program and here is how it looks like : t= world p = 1073841448 ptr = 1073841184 a = world 3210973408 ptr = world 3210973404 p = world 3210973400 stack is growing towards lower address space as ptr has value 3210973404 and when I strcpy it should overright pointer p and I sould't have the correct print value for p , right ?
@SelectCall No, that's not right at all. The addresses of your pointers are predictable, not their values. The fact that t, p, and ptr are at memory addresses next to each other does not mean their values would be anything close to their addresses. Their values would be what remained on the stack from previous runs - some completely unpredictable junk. Sometimes that junk "points" to some place in memory modifying which does not cause an immediate crash. That's a big misfortune, really.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.