Thread: Quick question about SIGSEGV

  1. #1
    Registered User
    Join Date
    Mar 2004
    Posts
    23

    Quick question about SIGSEGV

    I HATE SIGSEGV. Why is C programming so much harder than all the other langs? (don't answer that).
    Anyway look at the following:
    Code:
    int main (void)
    {
       char* p = "hello";
       ...
       printf("\n %s.", p);
       return 0;
    }
    There is no manipulation of p during ... . I've also tried
    printf(" %s ", *p);
    ======================
    char p[] = "hello";
    printf(" %s ", p); OR printf(" %s ", *p);

    All of the above gave me a segmentation fault.
    What is wrong? Please? I'm slowly giving up hope of ever learning C. I took a course in JAVA in school and was at the top of the class, but memory and string operations in C are SOOOOOO confusing.
    If pointers have made you suicidal, you're not alone. But there is no need to hurt yourself. There are people who are willing to help. Just call your local C Crisis Centre and talk to the professtionals there. If you don't have a C3 in your neighborhood, go to the global C3 at www.cprogramming.com . If you're still suicidal, don't lose hope. Gently close your book on C and throw it in the fireplace. If you live in a tower, you can throw it out the window. There, doesn't that feel better?

  2. #2
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    did you remember to
    Code:
    #include <stdio.h>
    And seg faults are your friend. They keep bad things from happening.

  3. #3
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    This works fine:
    Code:
    #include <stdio.h>
    
    int main (void)
    {
       char* p = "hello";
       printf("\n %s.", p);
       return 0;
    }
    If you find it doesn't, post all of your code (within reason )

    >>printf(" %s ", *p);
    This won't work.

    >>char p[] = "hello";
    >>printf(" %s ", p);
    This will work.

    >>printf(" %s ", *p);
    This won't work.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  4. #4
    Registered User
    Join Date
    Mar 2004
    Posts
    23
    Yes, stdio.h is there.
    And I realize that seg faults are good things, I just blame my lack of skills in C on them. Because 1 out of 2 errors I make in C are seg faults because I don't fully understand memory, strings and pointers.
    If pointers have made you suicidal, you're not alone. But there is no need to hurt yourself. There are people who are willing to help. Just call your local C Crisis Centre and talk to the professtionals there. If you don't have a C3 in your neighborhood, go to the global C3 at www.cprogramming.com . If you're still suicidal, don't lose hope. Gently close your book on C and throw it in the fireplace. If you live in a tower, you can throw it out the window. There, doesn't that feel better?

  5. #5
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  6. #6
    Registered User
    Join Date
    Mar 2004
    Posts
    23
    Code:
    int main (void)
    {
            char* s;
            char* p = "hello";
            printf("Programme to reverse all elements in a string, using recursion.");
            printf("\nYou will be required to enter a word up to 20 letters long.\n");
                                                                                                                    
            printf("WORD: HELLO");/*
            p = strin(stdin);*/
                                                                                                                    
            printf("\n %s", p); <==== SIGSEGV
                                                                                                                    
            s = reverse(p);
                                                                                                                    
            puts(s);
            return 0;
    }
    I won't post the rest of the code, namely the reverse function, because that part isn't even reached when seg fault occurs. The part of the programme we're talking about is just a normal assignment and output.
    If pointers have made you suicidal, you're not alone. But there is no need to hurt yourself. There are people who are willing to help. Just call your local C Crisis Centre and talk to the professtionals there. If you don't have a C3 in your neighborhood, go to the global C3 at www.cprogramming.com . If you're still suicidal, don't lose hope. Gently close your book on C and throw it in the fireplace. If you live in a tower, you can throw it out the window. There, doesn't that feel better?

  7. #7
    Registered User
    Join Date
    Mar 2004
    Posts
    23
    Oh, here's the output:
    Code:
    $ ./0ex4-13
    Programme to reverse all elements in a string, using recursion.
    You will be required to enter a word up to 20 letters long.
    WORD: HELLO
    Segmentation fault
    If pointers have made you suicidal, you're not alone. But there is no need to hurt yourself. There are people who are willing to help. Just call your local C Crisis Centre and talk to the professtionals there. If you don't have a C3 in your neighborhood, go to the global C3 at www.cprogramming.com . If you're still suicidal, don't lose hope. Gently close your book on C and throw it in the fireplace. If you live in a tower, you can throw it out the window. There, doesn't that feel better?

  8. #8
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    The problem is your reverse function. You're trying to modify a string literal. It seems like the problem is the print statement, but because you don't have an fflush after the printf or a newline at the end of the format string, the buffer isn't flushed and you don't see the output before reverse is called. Change your print to this and see what happens:
    Code:
    printf("\n %s\n", p);
    Then change your declaration to this and see the problem vanish:
    Code:
    char p[] = "hello";
    My best code is written with the delete key.

  9. #9
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    If you comment out the call to reverse(), your code runs fine. Post something that actually fails, and it'll be easier for us to help.

    My guess though, is that reverse writes to the memory that p points to, which would be wrong.

    If you have a pointer to a string literal, like so:
    >>char *p = "hammer";
    you cannot safely write over the word like this:
    *p = 'a';
    To do that, you'd need an array, like so:
    >char p[] = "hammer";
    then you can do:
    *p = '2';
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  10. #10
    Registered User
    Join Date
    Mar 2004
    Posts
    23
    Let me start by asking how long you've been doing C, prelude?
    Now, I have two problems:
    1) what happened to the previous output? Without the \n, should the output have been:
    WORD: HELLO
    helloSegmentation Fault
    ??

    (I changed the declaration to p[] = "hello"; with no change in the output.)
    2) The prototype for reverse is this
    char* reverse(char* s);
    During the function execution, contents of s are changed many times. I realize that 's' is a pointer to 'p' which points to the string "hello". How is manipulating it illegal? When can you manipulate strings with their pointers? and how should I pass the contents of p to reverse the correct way? should I make a new string in reverse and copy p to that?

    BTW: Thank you to all you guys: every time I post on this forum I'm bombarded with helping hands immediately (I say that literally). This is in contrast to some OS forum that I joined that takes a week just to activate an account.

    EDIT: I just read your post hammer. I was under the impression that a char* is an array!!!
    Last edited by Cikotic; 06-28-2004 at 05:07 PM.
    If pointers have made you suicidal, you're not alone. But there is no need to hurt yourself. There are people who are willing to help. Just call your local C Crisis Centre and talk to the professtionals there. If you don't have a C3 in your neighborhood, go to the global C3 at www.cprogramming.com . If you're still suicidal, don't lose hope. Gently close your book on C and throw it in the fireplace. If you live in a tower, you can throw it out the window. There, doesn't that feel better?

  11. #11
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    pointers are NOT arrays. They can use array subscripting but they are not arrays.

  12. #12
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Let me start by asking how long you've been doing C, prelude?
    Coming up on ten years. Wow, kinda scary.

    1) You would think so, but the implementation's error messages can do whatever they like, including a printing a leading newline as well as a trailing newline to ensure that the message begins at column 0 on its own line so as to be easier to see.

    2) There's a surprisingly huge difference between char *p and char p[]. The first is a pointer. When you assign a string literal to that pointer, it points to read-only memory (the address of the string literal). You can't modify read-only memory through that pointer, so any attempt will probably blow up in your face. The second is an array. When you assign a string literal to an array in a declaration, it actually copies the contents of the string literal into the memory of the array. The array is non-const memory owned by your process, so you can modify it at will. It's unfortunate that the two syntaxes that look so similar do something so wildly different, especially with the usual confusion of array and pointer equivalence.
    My best code is written with the delete key.

  13. #13
    Registered User
    Join Date
    Mar 2004
    Posts
    23
    >>Let me start by asking how long you've been doing C, prelude?
    >Coming up on ten years. Wow, kinda scary.
    Good: I still have nine and a half years to actually learn C. LOL.
    Anyway, so if I have
    char p[] = "hello";
    char *s;
    and I want to pass it to reverse, will this work?
    s = reverse(p);
    I assume not but how can I pass the array to the function, so that the function can manipulate it?
    Thinking about your explanation about the difference between pointers and arrays, prelude, I ask this: if pointers are read-only, then howcome functions like fgets take a pointer as an argument and change it so it points to something different ?
    I appreciate all your help. And thanx to Hammer for the links. On a personal note, hammer, Binky and I have become good friends and I'll start reading the other stuff on that site right now.
    If pointers have made you suicidal, you're not alone. But there is no need to hurt yourself. There are people who are willing to help. Just call your local C Crisis Centre and talk to the professtionals there. If you don't have a C3 in your neighborhood, go to the global C3 at www.cprogramming.com . If you're still suicidal, don't lose hope. Gently close your book on C and throw it in the fireplace. If you live in a tower, you can throw it out the window. There, doesn't that feel better?

  14. #14
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I was under the impression that a char* is an array!!!
    This statement warrants a reply of its own.

    Let me begin by saying that arrays and pointers are not the same. Arrays can be simulated with pointers and dynamic memory, and arrays are converted to a pointer to the first element of the array when used in a value context. This seeming equivalence is what confuses people so much, even experienced C programmers with decades of experience.

    So what is an array? An array is a block of memory equivalent to the size of N * sizeof(T) where T is the type of the array and N is the size. This is what an array object is.

    What is a pointer? A pointer is an object that holds an address, nothing more. That's what a pointer object is.

    Now, this is obvious until you see how C treats the two. You'll see pointers with array subscripting notation and arrays being dereferenced with a pointer offset, you'll see functions that take arrays being passed pointers and vice versa, you'll see all kinds of funky stuff (highly technical term!) that would suggest pointers and arrays are actually interchangeable. The problem is context. There are two contexts when it comes to array and pointer equivalence: value context and object context.

    Object context is when you use an array as an array and a pointer as a pointer; a good example of this is the sizeof operator. The following will print what you expect it to because the sizeof operator is working in object context:
    Code:
    #include <stdio.h>
    
    int
    main(void)
    {
      char  array[10];
      char *pointer;
    
      printf("Array:   %lu\n", (unsigned long)sizeof array);
      printf("Pointer: %lu\n", (unsigned long)sizeof pointer);
    
      return 0;
    }
    On my system this prints
    Code:
    Array:   10
    Pointer: 4
    Which is expected because the array is 10 characters, each 1 byte in size and a pointer object is 4 bytes on my system. This is object context, and there aren't many places where it applies in C. The places it applies are the following:

    1) As operands to the sizeof operator.
    2) As operands to the address-of (&) operator.
    3) A string literal initializer for an array.

    That last one is confusing until you realize that the type of a string literal is actually array-of-char. These are the three situations where an array is not equivalent to a pointer. I say "equivalent" because an array is never a pointer, and a pointer is never an array, but the language rules allow for certain conversions that make it seem that way. This brings us to the value context.

    Put simply, in value context, you get the value of an object. If that object is int, you ask for the integer contained within the memory owned by that variable. If the object is a pointer, you ask for the address that the pointer contains. If the pointer is dereferenced, you ask for the value of the type being pointed to that is contained at that address. And if the object is an array, it is converted to a pointer to the first element of the array. This conversion causes no end of confusion because once the array is converted to a pointer, you can use it much like a pointer (but not exactly like one).

    The subscript operator actually works with pointers. It takes a pointer and dereferences an offset of that pointer, that's why you'll hear time and again that [I]a is equivalent to *(a + i) and that because addition is commutitive, i[a] is equivalent to [I]a. For some reason teachers explain that last fact with great pride as if it's useful at all. In fact, array notation underneath is the dereference of an offset. It's merely syntactic sugar to make your life easier.

    When you pass an array to a function, the array notation is also syntactic sugar to tell you that you're going to use the pointer like an array, just like subscripting. These two function declarations are exactly the same:
    Code:
    void foo(char *array);
    Code:
    void foo(char array[]);
    In the end, array is a pointer, not an array. You can test this fact for yourself simply by trying to use array in object context within foo:
    Code:
    #include <stdio.h>
    
    void foo(char array[]);
    
    int
    main(void)
    {
      char array[10];
    
      foo(array);
    
      return 0;
    }
    
    void
    foo(
      char array[]
      )
    {
      printf("Array: %lu\n", (unsigned long)sizeof array);
    }
    You'll be surprised at first to see that the output is 4 (on my system ) instead of 10. That's because when array is passed to foo, it's used in value context and converted to a pointer to the first element. Then sizeof is used on the pointer in object context. Perfectly logical and natural to the trained eye, but hopelessly confusing to the beginner and unwary alike.

    But if an array in value context is a pointer, why can't we assign to it? Because that particular pointer is not an lvalue, so it can never be on the left hand side of an assignment. That's why I said that arrays can be used "much like" pointers, but not "exactly like" pointers. The reason we could modify the array that was passed to foo is because it's a copy of the pointer, not the original pointer, and the copy is an lvalue. But that's getting into function argument passing rules and this explanation is about pointers and arrays.

    So we can break it down into a few simple rules:

    1) Arrays and pointers are not the same.
    2) In value context, an array is a pointer to the first element of the array, but is not an lvalue.
    3) Array notation can work with pointers because it's syntactic sugar covering up pointer operations.
    4) Pointer notation can work with arrays because it's in a value context.
    5) There are three object contexts: sizeof, address-of, and string literal initialization.
    6) Everything else is value context.
    My best code is written with the delete key.

  15. #15
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Anyway, so if I have
    char p[] = "hello";
    char *s;
    and I want to pass it to reverse, will this work?
    s = reverse(p);
    Yes, it will. If I'm judging your reverse correctly, it takes an array, reverses it, and returns a pointer to the reversed array. So after reverse, p is "olleh" and s points to that string. All is well with the world.

    >if pointers are read-only, then howcome functions like fgets take a
    >pointer as an argument and change it so it points to something different ?
    Pointers aren't read-only, the memory for a string literal is. So if you have a pointer to a string literal, you can't dereference the pointer and modify the contents of the string. If the pointer points to memory that you own and is non-const, you can modify it all you want.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Very quick math question
    By jverkoey in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 10-26-2005, 11:05 PM
  2. very quick question.
    By Unregistered in forum C++ Programming
    Replies: 7
    Last Post: 07-24-2002, 03:48 AM
  3. quick question
    By Unregistered in forum C++ Programming
    Replies: 5
    Last Post: 07-22-2002, 04:44 AM
  4. Quick Question Regarding Pointers
    By charash in forum C++ Programming
    Replies: 4
    Last Post: 05-04-2002, 11:04 AM
  5. Quick question: exit();
    By Cheeze-It in forum C Programming
    Replies: 6
    Last Post: 08-15-2001, 05:46 PM