-1

Please explain what's going on in the following program.

I checked out the addresses returned by strerror(errno) at the beginning and end of the program and it confirms that it returns the same address each time.Then once sure of this,in first case I proceeded to assign that same address to ptr and then copy a string "Hello" to it using strcpy().In case II,I tried to copy "Hello" directly to the address returned by strerror(errno).I had odd findings.I'll appreciate if you explain the following:

In case one,I copied "Hello" to ptr and it is successful as in the subsequent printf(),ptr prints Hello.But then, when I passed strerror(errno) instead of ptr to printf(),it prints the old error message.How is it possible that ptr points to one message but strerror(errno) points to another message when both addresses are same?I verified both addresses are same and I expect that copying "Hello" to ptr should be same as copying it to the return of strerror(errno).To doubly check this discrepancy,then I tried to copy "Hello" directly to strerror(errno) but it doesn't work this time too and it prints the same old error string.But the surprising thing is,at this point too, I verified again that the addresses ptr and strerror(errno) are indeed same all along!! How is it possible?If they are same how are they pointing to different strings?One to "Hello" and other to the old custom error message?

Please explain the reason behind this.

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main ()
{ char *ptr;
  FILE * fp;
  fp = fopen ("missingfile.txt","r");
  if (fp == NULL)
    printf ("%s\n",strerror(errno));
    printf("\n%p",strerror(errno));  //Initial address

    //Case1:
    ptr=strerror(errno);
    strcpy(ptr,"Hello");
    printf("\n%s",ptr);  //Prints Hello
    printf("\n%s",strerror(errno)); //Still prints old message


    //Case2:
    strcpy(strerror(errno),"Hello"); //Doesn't copy Hello there
    printf("\n%s",strerror(errno)); //Still prints old message


    printf("\n%p",strerror(errno)); //Address same as it was at start
    printf("\n%p",ptr);  //same address as above statement


  return 0;
}

OUTPUT

No such file or directory

00032508
Hello
No such file or directory
No such file or directory
00032508
00032508
Rüppell's Vulture
  • 3,583
  • 7
  • 35
  • 49
  • You cannot do this, why are you trying to do this? It make no sense. – Jonatan Goebel May 14 '13 at 15:23
  • @JonatanGoebel Actually I had read that `The returned pointer points to a statically allocated string, which shall not be modified by the program`.I was only tinkering with it and was surprised to see how the same address can be of two different strings,one `Hello` and other the custom error message.`ptr` has `Hello` while the return of `strerror(errno)` has other message ,but both `ptr` and `strerror(errno)` are the same address all along!!! – Rüppell's Vulture May 14 '13 at 15:32

2 Answers2

6

In

//Case2:
strcpy(strerror(errno),"Hello"); //Doesn't copy Hello there
printf("\n%s",strerror(errno));

Your second call to strerror in the printf overwrites what you copied.

This is bad-form, all the way around.

Richard Sitze
  • 8,262
  • 3
  • 36
  • 48
3

From the manual page:

This string must not be modified by the application, but may be modified by a subsequent call to strerror().

So while the function doesn't return a const pointer, it should nevertheless not be modified, and that includes copying to it.

The strerror may in fact have a static buffer, which is the reason you get the same pointer returned from it.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • But how then I managed to copy to that string address indirectly using `ptr`?I managed to copy as printing `ptr` shows,but surprisingly, it doesn't show the same result when I pass `strerror(errno)` as argument to `printf()` even though I have used `ptr=strerror(errno)` and doubly verified before and again both addresses are same. – Rüppell's Vulture May 14 '13 at 15:15
  • 2
    Even more authoritative, the standard says "The strerror function returns a pointer to the string, the contents of which are locale- specific. **The array pointed to shall not be modified by the program**, but may be overwritten by a subsequent call to the strerror function." A "shall not" violation that means undefined behaviour. – Daniel Fischer May 14 '13 at 15:17