Thread: segfault with gcc, but not with TC

  1. #1
    root koodoo's Avatar
    Join Date
    Oct 2005
    Location
    a small village faraway in the mountains
    Posts
    28

    Unhappy segfault with gcc, but not with TC

    Consider the following program.
    Code:
    #include <stdio.h>
    int main()
    {
    char *a = "Hello";
    a[2] = 'a';
    return 0;
    }
    This program compiles fine, without any error/warning messages. On TC it even executes okay(if I print the string pointed to by a, it prints Healo), however with gcc on execution it gives a segmentation fault.
    Now I know that TC and gcc are different in some ways like :
    1) TC uses 16 bit pointers while gcc uses 32 bit pointers
    2) gcc conforms to the ansi version of C, more that TC
    I may be wrong about these differences but this is what I know.

    Whatever the differences may be, I could not understand why it gives the segfault error with gcc.
    Help needed.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    String literals are not writable on most platforms.

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    gcc does have (or at least used to) the compile option --writable-strings, but it's better to just do it correctly in the first place:
    Code:
    #include <stdio.h>
    int main(void)
    {
    char a[] = "Hello";
    a[2] = 'a';
    return 0;
    }
    or:
    Code:
    #include <stdio.h>
    int main(void)
    {
    char *a;
    a = malloc(6);
    strcpy(a, "Hello");
    a[2] = 'a';
    free(a);
    return 0;
    }
    If you understand what you're doing, you're not learning anything.

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by itsme86 View Post
    gcc does have (or at least used to) the compile option --writable-strings, but it's better to just do it correctly in the first place:
    I believe it's -fwritable-strings. It's something I'd NEVER recommend using -- why would you modify a string literal?

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Quote Originally Posted by brewbuck View Post
    I believe it's -fwritable-strings.
    You're right.

    why would you modify a string literal?
    Laziness?
    If you understand what you're doing, you're not learning anything.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by itsme86 View Post
    You're right.


    Laziness?
    It's a terrible idea. It forces the compiler to turn off string merging. It makes your program larger (potentially much, much larger)

  7. #7
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I'm not saying I do it (I don't). I was just trying to expand on your terse (mostly correct) response to the OP.
    If you understand what you're doing, you're not learning anything.

  8. #8
    root koodoo's Avatar
    Join Date
    Oct 2005
    Location
    a small village faraway in the mountains
    Posts
    28

    Thumbs up

    Thank You all, that solved it completely. But now I have one more question. I tried the following code :
    Code:
    #include <stdio.h>
    int main()
    {
    const int a=10;
    int *b = &a;
    *b=20;
    printf("%d\n", a);
    return 0;
    }
    when I compiled it, I got the following warning:
    Code:
    koodoo@knapsacker:~$ gcc prog.c -o prog
    prog.c: In function `main':
    prog.c:5: warning: initialization discards qualifiers from pointer target type
    koodoo@knapsacker:~$
    But when I executed it, I got the following result:
    Code:
    koodoo@knapsacker:~$ ./prog
    20
    koodoo@knapsacker:~$
    How do I explain this now?

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by koodoo View Post
    But when I executed it, I got the following result:
    Code:
    koodoo@knapsacker:~$ ./prog
    20
    koodoo@knapsacker:~$
    The "const" tells the compiler not to allow changes to the variable. However, you can take its address and cast it into a pointer to non-const. The compiler rightly complains when you do this, but it doesn't PREVENT you from doing it.

    Altering a string literal, and casting away the const-ness of a pointer, are both awful things to do.

  10. #10
    root koodoo's Avatar
    Join Date
    Oct 2005
    Location
    a small village faraway in the mountains
    Posts
    28
    k, I fully agree that they are awfull thing to do.
    But doesn't the second scenario in a way contradict the first one as far as C is concerned ?.
    Shouldn't there be more consistency in the way C handles the constants.

    I mean if it stores the string literal in a segment that's marked readonly, shouldn't the constant integer a be stored in the same segment so that it again gives a segfault at runtime?

    It's just a thought.

  11. #11
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Don't confuse "constants" with the "const" type qualifier. They don't mean exactly the same thing in C. And yes, it can be confusing.
    If you understand what you're doing, you're not learning anything.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by koodoo View Post
    Shouldn't there be more consistency in the way C handles the constants.

    I mean if it stores the string literal in a segment that's marked readonly, shouldn't the constant integer a be stored in the same segment so that it again gives a segfault at runtime?

    It's just a thought.
    You're right on the money. This is widely considered to be a deficiency of the C language. But remember that C was originally designed as a "portable assembler" intended primarily for implementing system-level software. At the system level, there are often legitimate reasons to do weird things like this.

    In C++, the meaning of "const" has been somewhat altered to align it more with the concept of a "constant."

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > shouldn't the constant integer a be stored in the same segment so that it again gives a segfault at runtime?
    Except your 'TC' isn't running on a protected OS. Even if TC puts the strings into the text segment, that still won't stop you from modifying the strings.
    16-bit DOS knows nothing about such things, no matter where you trample in memory.

    Segfaults are a function of the OS, not the language.

    Or consider an embedded platform, where the strings are stored in ROM. You can try as much as you want to modify the string. It won't happen of course (it's ROM), but neither is it likely to cause any kind of exception.

    So you have 3 possible outcomes, all of which are valid
    - it works,
    - it doesn't work,
    - you die trying.

    Which is why you need to learn the language from understanding good quality reference material, not from reverse engineered observations of a couple of compilers.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    Jan 2007
    Posts
    330
    Quote Originally Posted by itsme86 View Post
    You're right.


    Laziness?
    if you suddenly have to support code that abuses this the option comes in handy

  15. #15
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Salem View Post
    > shouldn't the constant integer a be stored in the same segment so that it again gives a segfault at runtime?
    Except your 'TC' isn't running on a protected OS. Even if TC puts the strings into the text segment, that still won't stop you from modifying the strings.
    16-bit DOS knows nothing about such things, no matter where you trample in memory.
    Just a quick side note, Salem: Borland/Inprise have resurrected the Turbo name for some of their recent compilers/development environments. Those compilers are 32 bit.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. malloc() resulting in a SegFault?!
    By cipher82 in forum C++ Programming
    Replies: 21
    Last Post: 09-18-2008, 11:24 AM
  2. Profiler Valgrind
    By afflictedd2 in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 09:38 AM
  3. Replies: 4
    Last Post: 09-02-2007, 08:47 PM
  4. Compiles on gcc 3.3 but not on gcc 4.0.3
    By cunnus88 in forum C++ Programming
    Replies: 5
    Last Post: 03-29-2007, 12:24 PM
  5. gcc
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 21
    Last Post: 10-22-2003, 03:46 PM