0

I tried the following program:

#include <stdio.h>

char s1[] = "Global String";
char *s2 = "Another Global String";

main()
{
    char s3[] = "Local String" ;
    char *s4 = "Another Local String" ;

    strcpy( s1, "New str" );
    strcpy( s2, "New str" ); // causes seg fault
    strcpy( s3, "New str" );
    strcpy( s4, "New str" ); // causes seg fault
}

s2 and s4 cause segmentation fault, presumably because they are stored in read-only data segment. How come the literal strings pointed by s1 and s3 don't crash? This is on Ubuntu.

Strangely, s1, s2, s3 and s4 can all be modified and no crash occurs when compiled with gcc on cygwin. Why is this?

simonc
  • 41,632
  • 12
  • 85
  • 103
  • 3
    See [**differences between char pointer and array**](http://stackoverflow.com/questions/1335786/c-differences-between-char-pointer-and-array) – Arnaud Le Blanc Jun 13 '13 at 10:00
  • 3
    Because pointers are not arrays and string **constants** are **constant** (what a surprise, really.) –  Jun 13 '13 at 10:01
  • 1
    why does work with cygwin? – user2460477 Jun 13 '13 at 10:04
  • @user2460477 It doesn't. It **seems** to work. –  Jun 13 '13 at 10:04
  • 4
    Guys :-), within 60 seconds of posting my question, I had 4 answers, none of which answered my question fully and then it is marked duplicate and I dont have the full answer (cygwin part). Possibly part of it was duplicate !! – user2460477 Jun 13 '13 at 10:07
  • 2
    @user2460477 hey don't worry. Post a new question. This time emphasizing the `cygwin` issue... like this works in cygwin why not in gcc? – pinkpanther Jun 13 '13 at 10:12
  • 2
    @user2460477 Attempting to modify the contents of a string literal results in undefined behaviour. The C standard doesn't specify what happens here - compiler vendors are free to implement whatever is convenient. Both crashing and appearing to work are acceptable examples of undefined behaviour. You've been unlucky that cygwin appeared to work with this incorrect code. – simonc Jun 13 '13 at 10:13
  • @simonc: Thanks. I was trying to find form the net if this is due to specifics of Windows executable (does it have a readonly data section?). Anyway, thanks for the answer – user2460477 Jun 13 '13 at 10:29

3 Answers3

5
char s1[] = "Global String";

reserves space for a writable buffer that contains a copy of the string literal.

char *s2 = "Another Global String";

declares a pointer to a read-only buffer containing the string literal.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
3

When you do char *s2 = "Another Global String";, s2 is a pointer that points to a string constant, and by doing strcpy( s2, "New str" ); you are trying to write on read only memory, that is illegal. For the same reason strcpy( s4, "New str" ); is not valid.

char s3[] = "Local String" ; makes s3 an array with the same length as the string constant (+1 for the trailing NULL). The string will be copied into that array, which you are free to modify.

phant0m
  • 16,595
  • 5
  • 50
  • 82
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
0

strcpy uses the memory that is prepared for it. If you have a static string, it may be in an non writable memory location, so if you copy a new string to it, it rightfully crashes.

You have to reserve memory first or use strdup.

Devolus
  • 21,661
  • 13
  • 66
  • 113