变量初始化和指针段错误
Variable initialization and pointer segfault
我在考虑指针初始化,尝试了以下两种情况:
#include <stdio.h>
int main(int argc, char **argv)
{
int *d;
int f;
int p;
*d = 6;
printf("%d %d %d\n", *d, f, p);
return 0;
}
此代码在行中出现段错误(在 gdb 中看到):
*d = 6;
这是有道理的,因为我正在尝试在随机地址存储一个值。
然后我尝试了以下操作:
#include <stdio.h>
int main(int argc, char **argv)
{
int *d;
int f = 10;
int p = 9;
*d = 6;
printf("%d %d %d\n", *d, f, p);
return 0;
}
运行完成并输出:
6 10 9
如果只有 f
初始化为 10(p
未初始化),反之亦然,程序仍然完成并输出
6 10 0
或
6 0 9
(p
已初始化)。我不明白为什么会这样。我最初的猜测是 f
或 p
的初始化使 space 或定向内存以允许 d
的安全初始化。我也考虑过堆栈分配,但我仍然不确定。
在你的程序中-
*d = 6; // writing to an invalid memory location
您将指针保留为未初始化的值。因此,当您取消引用它 (*d) 时,您会访问内存中未经授权的位置,从而导致分段错误。
你也尝试打印未初始化的局部变量-
printf("%d %d %d\n", *d, f, p); // where f and p are indeterminate
因此,您的代码调用 未定义的行为 并且您的程序给出的输出实际上可以是任何内容。
您的第一个问题出在 *d = 6;
,因为您正试图取消对无效指针的引用。
d
未初始化(分配的内存),它指向无效的内存位置。任何取消引用的尝试都会导致 undefined behavior.
FWIW,出于同样的原因,第二个代码也会生成 UB。
此外,在第一个代码片段中,通过编写
printf("%d %d %d\n", *d, f, p);
其中 f
和 p
是未初始化的自动局部变量,您正在尝试读取不确定的值,这又会产生 UB。在第二个片段中通过显式初始化避免了这种情况。
您需要使用 malloc() 分配内存
这项工作:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int *d;
int f = 10;
int p = 9;
d = /*(int *)*/malloc(sizeof(int) * 1);
if (!d)
exit(-1);
*d = 6;
printf("%d %d %d\n", *d, f, p);
free(d);
return 0;
}
This code segfaults at the line (seen in gdb):
*d = 6;
Which makes sense because I am trying to give random address to a
value.
段错误确实有道理,但你的解释是非常不正确的。您没有以任何方式为值提供/或分配地址。相反,您正试图在未指定的地址存储一个值。
了解 d
和 *d
之间的区别至关重要。前者(如您所声明的那样)是一个指针,预期用于保存 int
的地址。后者是 d
指向的 int
。事实上,如果 d
尚未初始化为指向 int
,则计算表达式 *d
会产生未定义的行为。
未定义的行为正是 -- 未定义。您不能指望类似的未定义行为源会在其他情况下产生相同的实际行为,您甚至不能依赖该行为来表现出明显的故障迹象。任何事情都可能发生,原则上包括程序员希望发生的事情。
声明指针变量不会自动导致分配任何存储空间。您可以通过多种方式初始化 d
,但其中一种是
d = &f;
我在考虑指针初始化,尝试了以下两种情况:
#include <stdio.h>
int main(int argc, char **argv)
{
int *d;
int f;
int p;
*d = 6;
printf("%d %d %d\n", *d, f, p);
return 0;
}
此代码在行中出现段错误(在 gdb 中看到):
*d = 6;
这是有道理的,因为我正在尝试在随机地址存储一个值。
然后我尝试了以下操作:
#include <stdio.h>
int main(int argc, char **argv)
{
int *d;
int f = 10;
int p = 9;
*d = 6;
printf("%d %d %d\n", *d, f, p);
return 0;
}
运行完成并输出:
6 10 9
如果只有 f
初始化为 10(p
未初始化),反之亦然,程序仍然完成并输出
6 10 0
或
6 0 9
(p
已初始化)。我不明白为什么会这样。我最初的猜测是 f
或 p
的初始化使 space 或定向内存以允许 d
的安全初始化。我也考虑过堆栈分配,但我仍然不确定。
在你的程序中-
*d = 6; // writing to an invalid memory location
您将指针保留为未初始化的值。因此,当您取消引用它 (*d) 时,您会访问内存中未经授权的位置,从而导致分段错误。
你也尝试打印未初始化的局部变量-
printf("%d %d %d\n", *d, f, p); // where f and p are indeterminate
因此,您的代码调用 未定义的行为 并且您的程序给出的输出实际上可以是任何内容。
您的第一个问题出在 *d = 6;
,因为您正试图取消对无效指针的引用。
d
未初始化(分配的内存),它指向无效的内存位置。任何取消引用的尝试都会导致 undefined behavior.
FWIW,出于同样的原因,第二个代码也会生成 UB。
此外,在第一个代码片段中,通过编写
printf("%d %d %d\n", *d, f, p);
其中 f
和 p
是未初始化的自动局部变量,您正在尝试读取不确定的值,这又会产生 UB。在第二个片段中通过显式初始化避免了这种情况。
您需要使用 malloc() 分配内存
这项工作:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int *d;
int f = 10;
int p = 9;
d = /*(int *)*/malloc(sizeof(int) * 1);
if (!d)
exit(-1);
*d = 6;
printf("%d %d %d\n", *d, f, p);
free(d);
return 0;
}
This code segfaults at the line (seen in gdb):
*d = 6;
Which makes sense because I am trying to give random address to a value.
段错误确实有道理,但你的解释是非常不正确的。您没有以任何方式为值提供/或分配地址。相反,您正试图在未指定的地址存储一个值。
了解 d
和 *d
之间的区别至关重要。前者(如您所声明的那样)是一个指针,预期用于保存 int
的地址。后者是 d
指向的 int
。事实上,如果 d
尚未初始化为指向 int
,则计算表达式 *d
会产生未定义的行为。
未定义的行为正是 -- 未定义。您不能指望类似的未定义行为源会在其他情况下产生相同的实际行为,您甚至不能依赖该行为来表现出明显的故障迹象。任何事情都可能发生,原则上包括程序员希望发生的事情。
声明指针变量不会自动导致分配任何存储空间。您可以通过多种方式初始化 d
,但其中一种是
d = &f;