繁体   English   中英

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

[英]What causes this integer pointer reassignment to crash?

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

int *a = 10;
*a = 100;

因为您试图将100写入可能未分配给程序的内存位置0x0000000A。 那是,

int *a = 10;

这并不意味着指针“ a”将指向内存中值为10的位置。这意味着它指向内存中的地址10(0x0000000A)。 然后,您想在该地址中写入内容,但是您没有“权利”,因为它没有分配

您可以尝试以下方法:

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

这将有效,尽管效率非常低下。 如果您只需要一个int,则应将其放入堆栈中,而不是堆中 在32位架构中,指针的长度为32位,而int的长度也为32位,因此,指向int的指针结构以这种方式占用( 至少 )8个字节的内存空间,而不是4个字节。而且我们甚至都没有提到缓存问题。

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

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

请参阅对另一个问题的回答,即对C保持谨慎。

对于所有建议使用malloc()为int分配内存的答案,我想对malloc()的使用提出一点更改。 代替:

a = malloc(sizeof(int));

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

long *a;

如果不更改分配,最终将分配错误的内存量(通常,在32位计算机上, intlong的大小通常相同)。 IMO,最好使用:

a = malloc(sizeof *a);

这仅表示“ a指向的类型的大小”,在这种情况下为int ,这当然是正确的。 如果您如上所述更改声明中的类型,则此行仍然正确。 如果您在赋值的左侧更改了变量的名称,但是仍然存在风险,但是至少您不再不必要地重复信息。

还要注意,在实际对象(即变量)上使用sizeof时,不需要带括号,而只需使用类型名称(看起来像强制转换表达式)即可。 sizeof不是函数,而是运算符。

因为您从未为a分配任何内存。 您刚刚为指向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

下一行,

int *a = 10;

定义一个指向整数a的指针。 然后将指针a指向存储位置10。

下一行

*a = 100;

将值100放入a指向的存储位置。

问题是:

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

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

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

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

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

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

可能是崩溃的原因是,您将指针分配给了您无法访问的内存部分,然后又向该内存位置分配了一些值(不允许这样做!)。

好的,今天尝试给出最简单的解释,同时尝试为您提供更详细的说明。 让我们加上一些括号吧?

(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都有一个大小标签,因此您无需声明为free -routine指向的块的大小。

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

0.1.2.3.4.5. 6
C h e e r y \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  

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

暂无
暂无

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

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