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

Ent*_*KEY 6 c pointers variable-assignment segmentation-fault

我写了一个C程序如下:

情况1

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

*a=11;

a=&b;/* store address of b in pointer variable*/
Run Code Online (Sandbox Code Playgroud)

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

我更改了代码如下:

案例2

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

a=&b;/* store address of b in pointer variable*/

*a=11;
Run Code Online (Sandbox Code Playgroud)

现在它工作正常.

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

pra*_*pta 17

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*/
Run Code Online (Sandbox Code Playgroud)

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

                               b
      +-------+            +--------+
      |       +            |   11   |
      |Unknown|            |        |
      +---+---+            +---+----+
          |                    |
          |                    |
          +                    +
          a                    a
CASE .2

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

a=&b;/* store address of b in pointer variable*/

*a=11;
Run Code Online (Sandbox Code Playgroud)

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

以上情况也不是指针声明的正确方法

  int *a  = NUll;
  a = malloc(sizeof(int));
  *a=5;
  free(a);//must
Run Code Online (Sandbox Code Playgroud)

要么

 int *a  = NUll;
 int b;
 a = &b;
 *a=5;
Run Code Online (Sandbox Code Playgroud)

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


Ama*_*nan 5

int *a; // a pointer variable that can hold a memory address of a integer value.
Run Code Online (Sandbox Code Playgroud)

在情况 1 中,

  *a = 10; // here you have asigned 10 to unknown memory address;
Run Code Online (Sandbox Code Playgroud)

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

在情况 2 中,

a=&b; // assigning a proper memory address to a.
*a=11;// assigning value to that address
Run Code Online (Sandbox Code Playgroud)

考虑这个例子:

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

Output: 10-->100
Run Code Online (Sandbox Code Playgroud)

这是它的工作原理。

         b        // name
     ----------
     +   10   +   // value
     ---------- 
        4000      // address 
Run Code Online (Sandbox Code Playgroud)

假设 b 的内存位置是 4000。

a=&b => a=4000;
*a=100 => *(4000)=100 => valueat(4000) => 100
Run Code Online (Sandbox Code Playgroud)

操作后是这个样子。

         b        // name
     ----------
     +  100   +   // value
     ---------- 
        4000      // address 
Run Code Online (Sandbox Code Playgroud)


pho*_*xis 5

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

一点解释:

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

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

           +----------+        +----------+
           |  garbage |        |  garbage |
           +----------+        +----------+
           |    a     |        |    b     |
           +----------+        +----------+
           |  addr1   |        |  addr2   |
           +----------+        +----------+
Run Code Online (Sandbox Code Playgroud)

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

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

您执行的下一条语句仅分配ina = &b的地址。这没有帮助,因为前一行已取消引用未初始化的指针。ba

接下来的代码在第三条语句之后有类似这样的内容:

           +----------+        +----------+
           |  addr2   |---+    |  garbage |
           +----------+   |    +----------+
           |    a     |   +--> |    b     |
           +----------+        +----------+
           |  addr1   |        |  addr2   |
           +----------+        +----------+
Run Code Online (Sandbox Code Playgroud)

第三条语句将地址分配给binto a。在此之前a没有取消引用,因此a初始化之前存储的垃圾值永远不会用作地址。现在,当您将知识的有效地址分配给 时a,取消引用a将使您能够访问 指向的值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;
}
Run Code Online (Sandbox Code Playgroud)

与从堆访问已释放内存位置的情况相同。

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