2
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *myptr = calloc(500,1);
    char *myptr2 = myptr;

    *myptr++ = 'A';
    *myptr++ = 'B';
    *myptr = '\0';
    /* This should dereference the beginning of the memory and print until myptr[2] which is '\0' */
    printf("Myptr2 points to: %s\n", *myptr2);

    free(myptr);

    return(EXIT_SUCCESS);
}

Why is line 13 (the printf line) creating a SIGSEV? It should be pointing to the beginning of the memory and then printf should print until it hits the '\0'.

the_endian
  • 2,259
  • 1
  • 24
  • 49
  • 5
    Very common mistake: you should _not_ dereference `myptr2` in the call to `printf`. – zwol Sep 04 '17 at 19:19
  • Change `%s` to `%c` in your `printf` – Ed Heal Sep 04 '17 at 19:19
  • 3
    @the_endian The pointer myptr was changed. So write free(myptr2); – Vlad from Moscow Sep 04 '17 at 19:20
  • @zwol can you tell conceptually what the problem is? If you dereference a pointer to the memory, what does this cause? – the_endian Sep 04 '17 at 19:23
  • 1
    Terrible newbie mistake to increment a pointer and then try to `free` it. – Weather Vane Sep 04 '17 at 19:26
  • 3
    Your compiler should warn about an invalid type. **Always** enable all recommended warnings and treat them as errors! – too honest for this site Sep 04 '17 at 19:26
  • I feel like this _has_ to be a duplicate, but I'm not having any luck finding something to dupehammer it to. The "[definitive list of common reasons for segmentation faults](https://stackoverflow.com/questions/33047452/definitive-list-of-common-reasons-for-segmentation-faults)" doesn't cover this case, but arguably should (and then again arguably _shouldn't_, since it's a C++ question so the commentariat will insist you ought to use iostreams instead). – zwol Sep 04 '17 at 19:34

2 Answers2

6

can you tell conceptually what the problem is? If you dereference a pointer to the memory, what does this cause?

When you have a %s slot in the format string, printf expects to see a char* as the corresponding argument. That's why you should pass myptr2 (which is the address of 'A' and from which the subsequent addresses of the string characters can be deduced).

If you pass *myptr2 instead, you are basically passing the character 'A' itself (with no information whatsoever as to where that particular 'A' is — which would have allowed printf to read the rest of the string). Simply put, printf expected a pointer there, so it attempts to treat the corresponding argument as a pointer.

Now notice that the character you passed (by dereferencing a char*, therefore getting a char with the value of 'A') has a size of 1 byte, while a pointer has a size of 4 or 8 bytes typically. This means that printf will most likely read a garbage address made up of a character and some random data found in the stack. There can be no guarantees as to what can happen to the program in this case, so the whole incident invokes undefined behavior.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
3

In your code, you should not dereference myptr2 in second argument of printf, so you have to replace:

printf("Myptr2 points to: %s\n", *myptr2);

with:

printf("Myptr2 points to: %s\n", myptr2);

When using %s with printf, you have to give the pointer on first character of the string.

Laurent H.
  • 6,316
  • 1
  • 18
  • 40