【问题标题】:Why memory is being modified without explicit modification为什么在没有显式修改的情况下修改内存
【发布时间】:2021-04-21 10:28:03
【问题描述】:

我一直在想,是一些与编译器相关的问题还是常规的 C 标准,在以下代码中无需请求即可更改某些内存:

void f(int* p)
{
    printf("Value of p: 0x%p\n", p);
    printf("Address of p: 0x%p\n", &p);
}

void scratch()
{
    int num = 1; //Dummy value
    int* num_p;
    num_p = #

    f(num_p);

    printf("Value of num_p: 0x%p\n", num_p);
    printf("Address of num_p: 0x%p\n", &num_p);
}

我的输出是:

Value of p: 0x009AFAC8
Address of p: 0x009AF9E8
Value of num_p: 0x009AFAC8
Address of num_p: 0x009AFABC

我的问题是:为什么在printf("Address of num_p: 0x%p\n", &num_p); 之后地址0x009AF9E8(包含0x009AFAC8)更改为包含0x009AFABC?嵌入式输出没有显示它,当我打开内存映射以查看指针 p 时,我检查了它。是因为最后一个printf导致编译器的一些调整,因为之前的函数不再使用它,它可以使用0x009AF9E8

【问题讨论】:

  • 没有任何改变,也没有编译器问题。您正在打印具有不同值的东西。
  • @WeatherVane:阅读最后一段中的问题。他们不是在询问“可观察的”程序行为。他们在询问他们在调试器中看到的内容。
  • 任何此类问题的答案都是:“as-if rule”。 任何事情都是可能的...可能...可能取决于编译器优化设置及其功能。
  • @IntToThe valid 没有任何改变。在第一种情况下,您打印传递给函数的指针变量在堆栈上 的副本的位置。在第二种情况下,您在main() 中打印它的位置。从函数返回后,该位置不再“拥有”。同样,在函数返回后,不能在函数中使用指向局部变量的指针。
  • @AnttiHaapala:不,这不是问题的答案。 OP 不是在问 C 标准说什么或理论上什么是可能的。 OP 使用了调试器,并专门询问他们程序的具体实现中发生了什么。事情确实发生了,他们观察到了,而且是有原因的。

标签: c function pointers memory arguments


【解决方案1】:

当您调用函数时,参数的值会复制到参数中。因此,当您将num_p 传递给f 时,会将值复制到本地p。由于它们是不同的变量(它们是指针的事实在这里无关紧要),它们具有不同的地址。

【讨论】:

  • 是的,我知道,实际上这不是我的问题。我想知道为什么使用已经过时的“p”地址来存储最后一个 printf 的输出
【解决方案2】:

因为在函数f返回后,编译器生成的程序将它用于参数p的内存用于另一个目的。几乎可以肯定,该内存在堆栈上,并且程序在调用 printf 期间重用了堆栈空间。

【讨论】:

  • 但是如果0x009AFABC 已经存储在其他地方(num_p 的地址),为什么还要更改0x009AF9E8 以包含0x009AFABC
  • @IntToThe:您调用了printf,向其传递了各种值,包括 0x009AFABC。一种可能是值被传递到处理器寄存器中,然后printf 设置为分析格式字符串并将传递的值转换为十六进制以进行打印。在做这项工作时,它可能已经保存了堆栈中涉及的一些值。所以 0x009AFABC 可能已经被放入了堆栈,而堆栈中的那个位置可能恰好是地址 0x009AF9E8。
【解决方案3】:

当您输入函数时,序言代码会为局部变量分配空间。

当您从函数返回时,结尾代码会释放此分配的内存。

由于大多数实现将堆栈用于局部变量,因此下一个调用的函数将为自己的局部变量重用相同的内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    相关资源
    最近更新 更多