为什么此C程序会导致记忆中的别名区域会导致分割故障


#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *myptr = calloc(500,1);
    char *myptr2 = myptr;
    *myptr++ = 'A';
    *myptr++ = 'B';
    *myptr = '';
    /* This should dereference the beginning of the memory and print until myptr[2] which is '' */
    printf("Myptr2 points to: %sn", *myptr2);
    free(myptr);
    return(EXIT_SUCCESS);
}

为什么创建一个sigsev行13(printf line)?它应该指向内存的开始,然后printf打印直到击中' 0'。

您可以从概念上说出问题是什么?如果您将指向记忆的指针放置,这将导致什么?

当您具有格式字符串中的%s插槽时,printf希望将char*视为相应的参数。这就是为什么您应该通过 myptr2'A'的地址,可以从中推导字符串字符的后续地址)。

如果您通过*myptr2,则基本上是传递字符'A'本身(没有任何有关该特定'A'在哪里的信息 - 它可以允许printf读取字符串的其余部分)。简而言之,printf期望在那里指针,因此它试图将相应的参数视为指针。

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

在您的代码中,您不应在printf的第二个参数中删除myptr2,因此您必须替换:

printf("Myptr2 points to: %sn", *myptr2);

with:

printf("Myptr2 points to: %sn", myptr2);

与printf一起使用%s时,您必须在字符串的第一个字符上给出指针。

最新更新