简体   繁体   English

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

[英]Pointer initialisation gives segmentation fault

I wrote a C program as follows: 我写了一个C程序如下:

CASE 1 情况1

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

*a=11;

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

It gives a segmentation fault when running the program. 它在运行程序时出现分段错误。

I changed the code as follows: 我更改了代码如下:

CASE 2 案例2

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

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

*a=11;

Now it's working fine. 现在它工作正常。

If anyone knows please explain why it is giving a segmentation fault in CASE 1. 如果有人知道请解释为什么它在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*/

This is going to be segmentation fault because the address you are using is not a valid address and there you are storing 11 which is illegal. 这将是分段错误,因为您使用的地址不是有效地址,并且您存储的是非法的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;

Now its working fine because the address of b is valid an there you are storing 11 which is legal. 现在它的工作正常,因为b的地址是有效的,你存储11是合法的。

Also above cases are not correct way of pointer declaration 以上情况也不是指针声明的正确方法

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

or 要么

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

This will remove segmentation fault many times which is hard to find . 这将很多次删除分段错误,很难找到。

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

In case 1, 在案例1中,

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

It shows segmentation fault because of assigning value to a memory address that is not defined. 它显示分段错误,因为将值分配给未定义的内存地址。 Undefined behaviour. 未定义的行为。

In case 2, 在案例2中,

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

Consider this example: 考虑这个例子:

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

Output: 10-->100

Here this is how it works. 这就是它的工作原理。

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

Asuuming memory location of b is 4000. 假设b的内存位置是4000。

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

After manipulation it looks like this. 操作后看起来像这样。

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

One line: First code you are dereferencing uninitialized pointer which exhibits undefined behaviour, and in the second code you are dereferencing initialized pointer which will give access to the value at the address. 一行:您正在取消引用未初始化指针的第一个代码,它表现出未定义的行为,而在第二个代码中,您将取消引用初始化指针,该指针将允许访问该地址的值。

A bit of explanation: 一点解释:

First you need to realize that a pointer is nothing but an integer, an with the *var we tell the compiler that we will be using the content of the variable var (the integer in it) as an address to fetch the value in that address. 首先,你需要认识到,一个指针只不过是一个整数,一个与*var我们告诉我们将要使用的变量的内容编译器var (其中的整数)作为地址在该地址来获取价值。 If there is **var similarly we tell the compiler that we will first use the stored value of the variable var to fetch the value at the address and again use this fetched value as an address and fetch the value stored in it. 如果有类似的**var我们告诉编译器我们将首先使用变量var的存储值来获取地址处的值,并再次使用此获取的值作为地址并获取存储在其中的值。

Therefore in your first declaration it is: 因此,在您的第一个声明中它是:

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

Then you try to use the value stored in a as an address. 然后尝试使用存储在a的值作为地址。 a contains garbage, it can be any value, but you do not have access to any address location. a包含垃圾,它可以是任何值,但您无权访问任何地址位置。 Therefore the next moment when you do *a it will use the stored value in a as an address. 因此,下一刻,当你做*a会在使用储值a作为地址。 Because the stored value can be anything, anything can happen. 因为存储的值可以是任何东西,任何事情都可能发生。

If you have permission to access the location , the code will continue to execute without a segmentation fault. 如果您有权访问该位置,则代码将继续执行而不会出现分段错误。 If the address happens to be an address from the heap book-keeping structure, or other memory area which your code allocated from heap or stack then when you do *a = 10 it will simply wipe off the existing value with 10 in that location. 如果地址恰好是来自堆簿保留结构的地址,或者代码从堆或堆栈分配的其他内存区域,那么当你执行*a = 10 ,它将在该位置用10擦除现有值。 This can lead to undefined behaviour as now you have changed something without the knowledge of the context having the actual authority of the memory. 这可能会导致未定义的行为,因为现在您已经更改了某些内容而不了解具有内存实际权限的上下文。 If you don't have permission to the memory, you simply get a segmentation fault. 如果您没有内存权限,则只会出现分段错误。 This is called dereferencing of an uninitialized pointer. 这称为取消引用未初始化的指针。

Next statement you do a = &b which just assigns the address of b in a . 你做下一个语句a = &b刚刚分配的地址ba This doesn't help, because the previous line has dereferenced an uninitialized pointer. 这没有用,因为前一行已取消引用未初始化的指针。

Next code you have something like this after the third statement: 下一个代码在第三个语句之后你有这样的东西:

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

The third statement assigns the address of b into a . 第三个语句将b的地址分配给a Before that a is not dereferenced, therefore the garbage value stored in a before the initialization is never used as an address. 在此之前, a未被解除引用,因此在初始化之前存储在a的垃圾值从不用作地址。 Now when you assign a valid address of your knowledge into a , dereferencing a now will give you access to the value pointed to by a . 现在,当你将你的知识的有效地址转换成a ,解引用a现在就可以访问到的值由指向a

Extending the answer, you need to keep an eye that, even if you have assigned a valid address to a pointer, you have to make sure at the time of dereferencing the pointer the lifetime of the address pointed to by the pointer has not expired. 扩展答案,你需要注意,即使你已经为指针分配了一个有效的地址,你必须确保在取消引用指针时指针所指向的地址的生命周期没有到期。 For example returning local variable. 例如,返回局部变量。

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;
}

Same in the case of accessing freed memory location from heap. 在从堆访问释放的内存位置的情况下也是如此。

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;
}

In the first case you have declared a pointer but you have not assigned the address to which it has to point hence the pointer would have contained an address that would have belonged to another process in the system (or it would have contained an junk value which is not an address at all or it would have contained an null which can't be an memory address)hence operating system sends an signal to prevent invalid memory operation and hence an segmentation fault occurs. 在第一种情况下,您已经声明了一个指针,但是您没有指定它必须指向的地址,因此指针将包含一个属于系统中另一个进程的地址(或者它将包含一个垃圾值,它根本不是地址,或者它将包含一个不能作为存储器地址的空值,因此操作系统发送信号以防止无效的存储器操作,因此发生分段故障。

In the second case you are assigning the address of the variable which has to be updated to the pointer and storing the value which is the correct way of doing and hence there's no segmentation fault. 在第二种情况下,您要将必须更新的变量的地址分配给指针并存储值,这是正确的操作方式,因此没有分段错误。

int a stores a random integer value. int a存储随机整数值。 So saying by saying *a, you might be accessing a memory location that is out of bounds or invalid. 所以说* a,你可能正在访问一个超出范围或无效的内存位置。 So it is a seg fault. 所以这是一个段错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM