是什么原因导致整数指针重新分配崩溃?

时间:2008-10-16 08:41:02

标签: c pointers

我是C的新手,我有这个问题。为什么以下代码崩溃:

int *a = 10;
*a = 100;

10 个答案:

答案 0 :(得分:20)

因为你试图将100写入内存位置0x0000000A,这可能没有分配给你的程序。也就是说,

int *a = 10;

并不意味着指针'a'将指向内存中具有值10的位置。这意味着它指向内存中的地址10(0x0000000A)。然后,你想在这个地址写一些东西,但你没有这样做的“权利”,因为它没有被分配

您可以尝试以下操作:

int *a = malloc(sizeof(int));
*a = 100;

这会起作用,虽然非常低效。如果您只需要一个int,那么您应该将其放入stack, not the heap。在32位架构上,指针长度为32位,int也是32位长,因此指向int的指针结构以这种方式占用(at least)8字节的内存空间4.我们甚至没有提到过缓存问题。

答案 1 :(得分:12)

您需要将指针指定给内存位置,而不是任意值(10)。

int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100;       // content of cell changed

请参阅my answer另一个问题,关注 C

答案 2 :(得分:7)

我想建议稍微改变malloc()的使用,以便建议使用它来为int分配内存。而不是:

a = malloc(sizeof(int));

我建议不要重复变量的类型,因为编译器已知并且手动重复它会使代码更加密集,并且会带来错误风险。如果您稍后将声明更改为例如

long *a;

在不更改分配的情况下,最终会分配错误的内存量(在一般情况下,在32位计算机上intlong通常大小相同)。这是IMO,更好用:

a = malloc(sizeof *a);

这仅仅意味着“a指向的类型的大小”,在本例中为int,这当然是完全正确的。如果您如上所述更改声明中的类型,则此行仍然正确。如果您更改作业左侧变量的名称仍然存在风险,但至少您不再需要不必重复信息。

另请注意,sizeof在实际对象(即变量)上使用时不需要括号,只能使用类型名称,类似于强制转换表达式。 sizeof不是函数,而是运算符。

答案 3 :(得分:2)

因为你从来没有为a分配任何内存。您刚刚为指向。

的指针分配了一些堆栈空间
int *a = NULL;

a = malloc (sizeof (int));

if (a != NULL)
{
*a =10;
}

会工作。

或者你可以给出一些现有变量的地址,这也可以。

int a* = NULL;
int b = 10;

a = &b;

现在这意味着做类似

的事情
*a = 100;

还将b设置为== 100

看看这个: http://home.netcom.com/~tjensen/ptr/pointers.pdf

答案 4 :(得分:2)

以下一行,

int *a = 10;

定义指向整数 a 的指针。然后,指向指针a到内存位置10。

下一行,

*a = 100;

将值100放在a指向的内存位置。

问题是:

  1. 你不知道指向哪里。 (您不知道内存位置的值10)
  2. 无论指向何处,您可能无权更改该值。它可能是其他程序/进程的一些内存。你小偷!

答案 5 :(得分:1)

因为您声明了一个指向int的指针,将指针初始化为10(一个地址),然后尝试为此地址的int赋值。由于地址10处的内存不属于您的进程,因此会崩溃。这应该有效:

int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);

答案 6 :(得分:1)

这段代码甚至可以编译吗? 10不能转换为int *,除非你像这样投射:

int *a = (int *) 10;
*a = 100;

在这种情况下,您尝试将100写入10的内存地址。这通常不是有效的内存地址,因此程序崩溃。

答案 7 :(得分:0)

它可能会崩溃,因为您将指针分配给您无权访问的内存的某些部分,然后您将一些值分配给该内存位置(您不允许这样做!)。< / p>

答案 8 :(得分:0)

好的,今天尝试给出最简单的解释,同时试图给你更详细的图片。让我们添加一些括号吗?

(int*) a = 10;
(*a) = 100;

您尝试将四个字节写入地址范围[10-13]。程序的内存布局通常更高,因此您的应用程序不会意外地覆盖任何可能的地方并且仍然起作用(例如来自.data,.bss和stack)。所以它最终会崩溃,因为地址范围尚未分配。

指针指向内存位置,C静态类型定义指针的类型。虽然你可以轻松覆盖指针。简单地:

(void*) v = NULL;

我们在这里进一步研究。什么是空指针?它只是指向地址0的指针。

您还可以为指针指定结构类型:

struct Hello {
    int id;
    char* name;
};

...

struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";

好的,什么是malloc? Malloc分配内存并返回指向已分配内存的指针。它具有以下类型签名:

void* malloc(size_t size);

如果您没有保守的垃圾收集器,很可能您的内存不会自动释放。因此,如果您希望从刚刚分配的内容中恢复使用内存,则必须执行以下操作:

free(hello_ptr);

你所做的每个malloc都有一个size-tag,所以你不需要说明你指向free -routine的块的大小。

好的,还有一件事,字符串在内存中的样子是什么?例如,类似于“Cheery”的那个。简单回答。它是一个以零结尾的字节数组。

0.1.2.3.4.5. 6
C h e e r y \0

答案 9 :(得分:0)

你也可以把它写成:

int* a = 10;
*a = 100;

注意第一行的不同间距。这不是一种流行的风格,但我个人认为它更清晰。它与编译器具有完全相同的含义。

然后,大声朗读:

"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"

代替实际值:

"Value-pointed-to-by 10 becomes 100"

...您意识到10不太可能指向您可以使用的内存。

你几乎不会分配一个带有文字的指针:

int* ptr = (int*)10;  // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime  

我猜可能会有一些非常低级别的作业,您可以直接指定绝对内存地址。例如内核实现?