为什么这个取消引用别名内存区域的C程序会导致分段错误?

the*_*ian 2 c segmentation-fault

#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);
}
Run Code Online (Sandbox Code Playgroud)

为什么第13行(printf行)创建了一个SIGSEV?它应该指向内存的开头,然后printf应该打印,直到它到达'\ 0'.

The*_*kis 6

你能从概念上讲出问题所在吗?如果取消引用指向内存的指针,这会导致什么?

如果%s格式字符串中有插槽,则printf希望将a char*视为相应的参数.这就是为什么你应该通过myptr2(这是地址'A',并从该字符串的字符随后的地址可以推断).

如果你传递了*myptr2,你基本上就是传递角色'A'本身(没有任何关于特定'A'位置的信息 - 这将允许printf读取字符串的其余部分).简单地说,printf期望指针在那里,所以它试图将相应的参数视为指针.

现在请注意,您传递的字符(通过取消引用a char*,因此得到char值为'A'a)的大小为1字节,而指针的大小通常为4或8字节.这意味着printf很可能会读取由字符和堆栈中的一些随机数据组成的垃圾地址.在这种情况下,无法保证程序会发生什么,因此整个事件会调用未定义的行为.