局部变量地址的返回

char *fun()
{
char str[] = "hello";
return str;
}

这个函数的返回值?以及这个函数在栈上的存储布局

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

char *fun()
{
    char ptr[] = "fda";              
    int a = 3;
    int b = 4;                                                                                                                      printf("test: %x %x %d\n", ptr, &ptr[1], sizeof(ptr)); 
    printf(" ptr a b :%x %x %x\n", ptr, &a, &b);
    return ptr;
}

int main(int argc, const char *argv[])
{
    char a1 = '7';
    char *p = fun();
    char a2 = '9';
    printf("a1 a2 p(fun): %x %x  %x\n", &a1, &a2, p);
    char a = 4;
    char b = 4;
    printf("%x %x\n", &a, &b);
    return 0;
}

 就函数而言,返回局部变量的地址这种做法是错误的,但是这个函数不管是在VS还是在gcc上编译时都只会有一个警告

 局部变量的地址在出了作用域后就没有意义了,可能被其他数据覆盖


➜  1009 git:(master) ✗ gcc test1.c
test1.c: 在函数‘fun’中:
test1.c:12:5: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
     return ptr;
     ^
➜  1009 git:(master) ✗ ./a.out 
test:bfe416fc bfe416fd 4
ptr a b :bfe416fc bfe416f8 bfe416f4
a1 a2 p(fun): bfe4171b bfe4171a  bfe416fc
bfe41719 bfe41718

可以看看地址的分布情况:

...171b                  a1

....171a                 a2

....1719                   a

.....1718                   b                       

.....分配给fun函数栈...

...

....16ff           ptr[3    '\0'

....16fe          ptr[2]   'a'

...16fd           ptr[1]   'd'

...16fc           ptr[0]    'f '        ---》如果字符串长度加1 不为4的倍数会有内存对齐

....16f8           int  a

....16f4          int   b


函数退出后再定义变量,又回到171a处


可以看出大致结构,给函数分配栈时并不是直接接着上面的,虽然函数退出后没有清空或者初始化刚刚函数占用的栈,但是后续的数据可以覆盖上去

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

char *fun()
{
    char ptr[] = "fda";
    int a = 3;
    int b = 4;
    printf(" fun :%x %x %d\n", ptr, &ptr[1], sizeof(ptr));
    printf("ptr a b :%x %x %x\n", ptr, &a, &b);
    return ptr;
}

int main(int argc, const char *argv[])
{
    char a1 = '7';
    char *p = fun();
    printf("p: %d\n", *p);
    char a2 = '9';
    printf("a1 a2 p(fun): %x %x  %x\n", &a1, &a2, p);
    char a = 4;
    char b = 4;
    printf("main a b :%x %x\n", &a, &b);
    printf("p: %d\n", *p);
    return 0;
}

结果:

 

➜  1009 git:(master) ✗ gcc test1.c 
test1.c: 在函数‘fun’中:
test1.c:12:5: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
     return ptr;
     ^
➜  1009 git:(master) ✗ ./a.out 
 fun :bffbedfc bffbedfd 4
ptr a b :bffbedfc bffbedf8 bffbedf4
p: 102
a1 a2 p(fun): bffbee1b bffbee1a  bffbedfc
main a b :bffbee19 bffbee18
p: -33

刚退出函数时打印的是函数中的那个字符  f对应的ascii值是102,  后面定义了2个int型 就把空间覆盖了导致输出的是-33







 

在编程中,避免返回局部变量地址是一个重要的编程实践。局部变量是在函数或方法内部定义的变量,它们在函数调用期间存在,函数执行完毕后,这些变量就会被销毁。如果返回局部变量地址可能会导致未定义行为或程序崩溃。以下是一些关键点: 1. **生命周期**:局部变量的生命周期仅限于函数或方法执行期间。一旦函数执行完毕,局部变量就会被销毁,指针指向的内存地址可能不再有效。 2. **未定义行为**:返回局部变量地址可能导致未定义行为。未定义行为是指程序的行为不可预测,可能导致程序崩溃、数据损坏或其他不可预测的问题。 3. **内存管理**:如果返回局部变量地址,调用者可能会尝试访问已经释放的内存,这会导致内存访问错误。 4. **解决方案**:为了避免这些问题,可以使用动态内存分配(如`malloc`或`new`)或返回指向静态变量、全局变量或通过引用传递的参数。 以下是一个示例,展示了如何避免返回局部变量地址: ```cpp #include <iostream> int* getLocalVariableAddress() { int localVar = 10; // 局部变量 return &localVar; // 返回局部变量地址 } int* getStaticVariableAddress() { static int staticVar = 10; // 静态变量 return &staticVar; // 返回静态变量的地址 } int main() { int* ptr1 = getLocalVariableAddress(); std::cout << "Local Variable Address: " << ptr1 << std::endl; // 未定义行为 std::cout << "Local Variable Value: " << *ptr1 << std::endl; // 未定义行为 int* ptr2 = getStaticVariableAddress(); std::cout << "Static Variable Address: " << ptr2 << std::endl; std::cout << "Static Variable Value: " << *ptr2 << std::endl; return 0; } ``` 在这个示例中,`getLocalVariableAddress`函数返回局部变量地址,这会导致未定义行为。而`getStaticVariableAddress`函数返回了静态变量的地址,这是安全的,因为静态变量在程序的生命周期内保持有效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值