c - 函数参数在 C 中表现异常

下面是用 C 编写的示例代码:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

int* second;
void myTest1(int a, bool check){
    if(check){
        second = &a;
    }
    printf("%d", *(second));
    printf(" ");
}
int main(int argc, char const *argv[])
{
    int a =1;
    int b = 2;
    int c=3;
    myTest1(a,true);
    myTest1(b,false);
    myTest1(c,false);
}

我希望输出是这样的

1 1 1

但实际输出是

1 2 3

我对此有点困惑,void myTest1(int a, bool check)在这里我相信a应该有功能范围。但是似乎a的内存位置在每个函数调用中重复使用。

我正在使用命令 gcc <filename>.c 进行构建

以下是一些系统详细信息:

  • 操作系统:Ubuntu
  • GCC编译器版本:gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

最佳答案

您正在将 second 设置为函数调用结束时超出范围的变量地址。一旦变量超出作用域,它占用的内存就不再是你的了,可以重用。该内存地址恰好在每次后续调用中重复使用,并将新参数的值复制到其中。

不要存储局部变量的地址并在变量超出范围后访问该地址。这会产生未定义的行为。您不能对该指针的另一端可能有什么做出任何假设。

关于以下内容:

here I believed a should have function scope

确实...

But it seems that the memory location of "a" is reused in every function call.

嗯,重用是 a 具有“功能范围”的必然和自然结果。除非您假设某种垃圾收集行为,即保留指向此内存的指针会阻止它被重用,a 的内存位置应该被重用一次 a 是不可访问的,否则这就是内存泄漏的定义。如果不重用函数参数的内存,则每次函数调用都会有意地泄漏内存。

在 C 和 C++ 中,您的工作是不存储已超出范围的堆栈分配变量的地址(或者至少,不要在变量超出范围后尝试使用该地址)。将地址存储在指针中的行为并不能天生就保护该内存不被重用。您可以自行决定在堆上分配该内存并管理其生命周期,或者允许堆栈管理您的内存而不保留比它们指向的变量的生命周期更长的指针。

https://stackoverflow.com/questions/72902821/

相关文章:

python-3.x - 在python中将字符串写入文本文件

python - 如何获取 Pandas 表中所有命名类别的最大值

laravel - "npm run watch"不工作并返回错误 's saying ' 缺少 "

node.js - 类型不可分配给 express-jwt 中的类型 'GetVerificatio

c - 打包的相同结构是否保证具有相同的内存布局?

java - HashMap.clear() 减少内存?

r - 如何在 R 中将向量分解为连续的组

c - C语言中如何减少或替换else if语句?

regex - 用awk模拟 "grep -oE"的停止条件

php - 如何确定数据是在 PHP 中增加还是减少