| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2569 人关注过本帖
标题:有关 函数调用和内存分配 的问题!
只看楼主 加入收藏
chrisgardner
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:73
专家分:114
注 册:2013-9-25
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:10 
有关 函数调用和内存分配 的问题!
这时书上的一个例子,代码如下:
程序代码:
#include <stdio.h>

long * IncomePlus(long *);

int main(void)
{
    long your_pay = 30000L;
    long * pold_pay = &your_pay;
    long * pnew_pay = NULL;

    pnew_pay = IncomePlus(pold_pay);

    printf("\nOldpay = $%ld", * pold_pay);
    printf("\nNewpay = $%ld", * pnew_pay);

    //printf("\nNewpay = $%ld", * pnew_pay);
    //printf("\nOldpay = $%ld", * pold_pay);
    //printf("\nOldpay = $%ld, Newpay = $%ld", * pold_pay, * pnew_pay);

    printf("\n\n");
    return 0;
}

long * IncomePlus(long * pPay)
{
    long pay = 0;
    pay = * pPay + 10000L;
    return &pay;
}

问题是:
1.函数 Incomeplus()中创建的变量 pay, 在函数调用结束后系统分配给它的内存有没有被释放?有没有被其他程序使用?pay 分配的内存是在堆中?还是堆栈中?
2.程序运行时,现实 Newpay 是一个垃圾值, 但是如果交换两个 printf 语句的顺序,或者将两个输出合并成一个输出, 输出貌似是正确的,这是为什么?跟内存分配有啥关系?

希望高手能指点一下,谢谢了!!!
2014-05-19 10:26
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
这段代码编译后 会给出这个提示

warning C4172: 返回局部变量或临时变量的地址


这就有很多不确定性 也可以说是错误的代码

DO IT YOURSELF !
2014-05-19 11:01
chrisgardner
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:73
专家分:114
注 册:2013-9-25
收藏
得分:0 
回复 2 楼 wp231957
这是书上的一个代码,确实是有问题的,但是我想知道错在哪里,书上解释的不是很清楚!
2014-05-19 11:05
funyh250
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:26
帖 子:290
专家分:1573
注 册:2013-12-25
收藏
得分:0 
long * IncomePlus(long * const pPay)
{
    * pPay  += 10000L;
    return pPay;
}

指针不变  改变指的内容

学习是大事   吃喝拉撒睡是小事   其他的那都不是事
2014-05-19 11:18
embed_xuel
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:58
帖 子:3845
专家分:11385
注 册:2011-9-13
收藏
得分:5 
初学者理解起来应该挺费劲的,入门的书上应该不讲这个吧?

总有那身价贱的人给作业贴回复完整的代码
2014-05-19 11:23
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:15 
局部變量pay分配在棧上,函數結束後已被原則上廢除,返回的是這個變量當時在棧上的地址,但這個地址隨時可能被程序其他的運行函數覆蓋使用(這就是“原則上”的意思),即有可能馬上被占用,也可能不馬上占用,結果是不確定的。地址確實可以返回,但對這個地址取數據卻未必是原先儲存的數據了。棧上的數據是否被占用,與程序的後續運行情況有關,再調用同樣的函數,數據是重新壓棧和分配的,該函數的起始地址也未必與上一次一樣,同樣名稱的局部變量,也未必會分配在同樣的棧地址上。其實你得到的結果衹是巧合,在兩次函數調用之間插入其他的語句,讓程序做點別的事情,把棧數據沖亂了,結果就會不一樣。

總之,記著書本上和編譯器的告誡:不要返回局部變量的指針或引用!

[ 本帖最后由 TonyDeng 于 2014-5-19 13:10 编辑 ]

授人以渔,不授人以鱼。
2014-05-19 12:03
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
簡單的記憶規則:棧上的數據容易變化,堆上的數據不容易變化。

授人以渔,不授人以鱼。
2014-05-19 12:06
funyh250
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:26
帖 子:290
专家分:1573
注 册:2013-12-25
收藏
得分:0 
来自360问答

内存的三种分配方式:
1. 从静态存储区分配:此时的内存在程序编译的时候已经分配好,并且在程序的整个运行期间都存在。全局变量,static变量等在此存储。
2. 在栈区分配:相关代码执行时创建,执行结束时被自动释放。局部变量在此存储。栈内存分配运算内置于处理器的指令集中,效率高,但容量有限。
3. 在堆区分配:动态分配内存。用new/malloc时开辟,delete/free时释放。生存期由用户指定,灵活。但有内存泄露等问题。

常见内存错误及对策
1. 内存分配未成功,却被使用。
对策:使用内存之前检查是否分配成功。用p!=NULL判断。
2. 内存分配成功,未初始化就被使用。
内存的缺省值没有统一的标准。大部分编译器以0作为初始值,但不完全是。
对策:内存初始化时赋初值。
3. 内存操作越界。
对策:只能是小心了。
4. 释放了内存,仍然使用。
(1) 使用显示delete和free的野指针。
对策:释放完内存,将指针置为NULL。
(2) 使用隐式delete和free的野指针。主要是指函数返回指向栈内存的指针或引用。
对策:当然是不要返回就可以了。
5. 未释放内存,导致内存泄露。
用new/malloc开辟了内存,没用delete/free释放.
对策:new和delete的个数一定相同;malloc和free的个数一定相同;new[]和[]delete一定对应。

学习是大事   吃喝拉撒睡是小事   其他的那都不是事
2014-05-19 12:17
chrisgardner
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:73
专家分:114
注 册:2013-9-25
收藏
得分:0 
回复 5 楼 embed_xuel
在《C语言入门经典》第四版中第八章有这么一个例子,但是书上解释的不清楚,尤其是为什么合并两个printf()语句后输出是正常的,我尝试交换两个printf()的顺序输出也是正常的,那本书解释的模棱两可!
2014-05-19 14:12
chrisgardner
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:73
专家分:114
注 册:2013-9-25
收藏
得分:0 
回复 6 楼 TonyDeng
谢谢你的答复,关于局部变量在栈上的操作你讲的很详细,我看懂了八九成,我尝试了在两个printf 前面插入了其他无关的语句,输出变化了,数据是垃圾值!
这是不是说明,之前交换输出顺序,先输出new_pay正确是因为还没有其他函数占用局部变量pay的内存,pay的内存空间暂时是“安全的”,但是如果交换输出顺序,先输出old_pay 或者在输出new_pay之前插入其他语句,那么pay这块空间就被使用了,里面的数据将不是之前存放的数据,会被覆盖,所以输出了垃圾值,以我目前的能力只能理解到这个程度了,还有很多不太懂的地方。
2014-05-19 14:33
快速回复:有关 函数调用和内存分配 的问题!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024686 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved