指针初始化给出了分段错误

我写了一个C程序如下:

情况1

int *a; /* pointer variable declaration */ int b; /* actual variable declaration */ *a=11; a=&b;/* store address of b in pointer variable*/ 

它在运行程序时出现分段错误。

我更改了代码如下:

案例2

 int *a; /* pointer variable declaration */ int b; /* actual variable declaration */ a=&b;/* store address of b in pointer variable*/ *a=11; 

现在它工作正常。

如果有人知道请解释为什么它在CASE 1中给出了分段错误。

 CASE .1 int *a; /* pointer variable declaration */ int b; /* actual variable declaration */ *a=11;//Not valid means you are not owner of the address where a now pointing it is unknown and accessing this will segfault/ a=&b;/* store address of b in pointer variable*/ 

这将是分段错误,因为您使用的地址不是有效地址,并且您存储的是非法的11。

  b +-------+ +--------+ | + | 11 | |Unknown| | | +---+---+ +---+----+ | | | | + + aa CASE .2 int *a; /* pointer variable declaration */ int b; /* actual variable declaration */ a=&b;/* store address of b in pointer variable*/ *a=11; 

现在它的工作正常,因为b的地址是有效的,你存储11是合法的。

上面的情况也没有正确的指针声明方式

  int *a = NUll; a = malloc(sizeof(int)); *a=5; free(a);//must 

要么

  int *a = NUll; int b; a = &b; *a=5; 

这将很多次删除分段错误,很难找到。

 int *a; // a pointer variable that can hold a memory address of a integer value. 

在案例1中,

  *a = 10; // here you have asigned 10 to unknown memory address; 

它显示分段错误,因为将值分配给未定义的内存地址。 未定义的行为。

在案例2中,

 a=&b; // assigning a proper memory address to a. *a=11;// assigning value to that address 

考虑这个例子:

 #include int main() { int *a,b=10; printf("\n%d",b); a=&b; *a=100; printf("-->%d",b); } Output: 10-->100 

这就是它的工作原理。

  b // name ---------- + 10 + // value ---------- 4000 // address 

假设b的内存位置是4000。

 a=&b => a=4000; *a=100 => *(4000)=100 => valueat(4000) => 100 

操纵后看起来像这样。

  b // name ---------- + 100 + // value ---------- 4000 // address 

一行:您正在取消引用未初始化指针的第一个代码,它表现出未定义的行为,而在第二个代码中,您将解除引用初始化指针,该指针将允许访问该地址的值。

一点解释:

首先你需要意识到一个指针只是一个整数,一个带有*var我们告诉编译器我们将使用变量var的内容(其中的整数)作为一个地址来获取该地址中的值。 如果有类似**var我们告诉编译器我们将首先使用变量var的存储值来获取地址处的值,并再次使用此获取的值作为地址并获取存储在其中的值。

因此,在您的第一个声明中,它是:

  +----------+ +----------+ | garbage | | garbage | +----------+ +----------+ | a | | b | +----------+ +----------+ | addr1 | | addr2 | +----------+ +----------+ 

然后尝试使用存储在a的值作为地址。 a包含垃圾,它可以是任何值,但您无权访问任何地址位置。 因此,当您执行*a ,它将使用a中的存储值作为地址。 因为存储的值可以是任何东西,任何事情都可能发生。

如果您有权访问该位置,则代码将继续执行而不会出现分段错误。 如果地址碰巧是来自堆簿保留结构的地址,或者代码从堆或堆栈分配的其他内存区域,那么当你执行*a = 10它只会在该位置用10擦除现有值。 这可能会导致未定义的行为,因为现在您已经更改了某些内容而不了解具有内存实际权限的上下文。 如果您没有内存的权限,则只会出现分段错误。 这称为取消引用未初始化的指针。

接下来的语句你做a = &b ,它只是在b中分配b的地址。 这没有用,因为前一行已取消引用未初始化的指针。

下一个代码在第三个语句之后你有这样的东西:

  +----------+ +----------+ | addr2 |---+ | garbage | +----------+ | +----------+ | a | +--> | b | +----------+ +----------+ | addr1 | | addr2 | +----------+ +----------+ 

第三个语句将b的地址分配给a 。 在此之前a未被解除引用,因此在初始化之前存储在a的垃圾值从不用作地址。 现在,当您将知识的有效地址分配到a ,取消引用now将允许您访问a指向的值。

扩展答案,您需要注意,即使您已为指针分配了有效地址,您也必须确保在取消引用指针时指针指向的地址的生命周期尚未到期。 例如,返回局部变量。

 int foo (void) { int a = 50; return &a; //Address is valid }//After this `a' is destroyed (lifetime finishes), accessing this address //results in undefined behaviour int main (void) { int *v = foo (); *v = 50; //Incorrect, contents of `v' has expired lifetime. return 0; } 

在从堆访问释放的内存位置的情况下也是如此。

 int main (void) { char *a = malloc (1); *a = 'A'; //Works fine, because we have allocated memory free (a); //Freeing allocated memory *a = 'B'; //Undefined behaviour, we have already freed //memory, it's not for us now. return 0; } 

在第一种情况下,你已经声明了一个指针,但你没有指定它必须指向的地址,因此指针将包含一个属于系统中另一个进程的地址(或者它将包含一个垃圾值,它根本不是地址,或者它将包含一个不能作为存储器地址的空值,因此操作系统发送信号以防止无效的存储器操作,因此发生分段故障。

在第二种情况下,您要将必须更新的变量的地址分配给指针并存储值,这是正确的操作方式,因此没有分段错误。

int a存储随机整数值。 所以说* a,你可能正在访问一个超出界限或无效的内存位置。 所以这是一个段错误。