C语言之内存使用

来源:本站
导读:目前正在解读《C语言之内存使用》的相关信息,《C语言之内存使用》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《C语言之内存使用》的详细说明。

这里我和大家一起探讨c语言的内存使用。

曾经有同行写了一个把整数转换为字符串的函数:

char *itoa (int n)

{

char retbuf[20];

sprintf(retbuf, "%d", n);

return retbuf;

}

倘若我调用该函数:char *str5 = itoa(5),str5会是什么数值?

结果是不确定,唯一能确定的是结果不会是我们想要的 “5”。

为何呢?因为retbuf定义在函数体中,它是局部变量,局部变量的内存空间位于堆栈(stack)中,同时其作用范围也仅限于所在的函数中。此时当itoa()函数返回时,retbuf在堆栈中的内容将被回收,这块内存地址将可能被存放别的内容。所以把局部变量返回给函数调用者是欠妥的,也是不应该的做法。

这样我们该如何解决问题呢,别担心,方法有很多且不止一个,下面就来阐述三种能解决这个问题的方法:

1)、在itoa()函数内部用malloc() 为指针分配内存,同时将结果存放到里面,最后将retbuf返回给调用者。因为此时retbuf分配于堆(heap)中,其对应空间不会随着函数返回而释放,所以能达到我们的目的。

不过这里需要注意:调用者在不需要retbuf的时候必须人工把它释放,调用free函数来回收空间,否则就造成内存泄漏了。倘若该函数和调用函数的都是同一个人所写则问题不大,否则将比较容易会疏漏此释放内存的动作。

2)、在itoa()函数内部定义静态变量static char retbuf[20],这同样能保证函数返回后retbuf的空间不被回收,这是因为静态变量并不是存放在堆栈中,而是存放在一个叫“.bss”段的地方,该地方的内容是不会因函数返回而被回收的。

这种办法虽然能解决问题,不过它也导致了函数变成了一个不可重入函数(即不能保证相同的输入肯定有相同的输出)。同时, retbuf [] 中的内容会被函数的下一次调用结果所代替,该办法不值得推荐。

3)、使用指针参数,将函数定义为char *itoa(int n, char *retbuf),并且retbuf由函数调用者申请和释放,这时候itoa()只是将转换结果存放到retbuf。

很明显这种方法比第一、二种方法强,首先避免了方法1对函数的影响,同时也规避了方法2对内存分配释放的影响,是业内一种比较通用流行的做法。

扩展分析:

如果就该问题本身而言,想必大家都可以迅速想到答案,问题关键就在对memory这类敏感资源的正确和合理地利用,下来我们对内存做个简单的分析:

1)、程序中分为不同的内存段,包含:

.heap - 堆,由程序显式分配和收回,如果不收回就是内存泄漏。

.bss - 未初始化全局/静态变量,在整个软件执行过程中有效;

.data - 已初始化全局/静态变量,在整个软件执行过程中有效;

.stack - 函数调用栈,其中的内容在函数执行期间有效,并由编译器负责分配和收回;

2)、自己管理的内存尽量自己申请和释放。

这其实是一个内存分配和释放的基本原则,比方说上面的第二种方法,由itoa()分配的内存,却由调用者释放,就不是一个十分好的做法,它明显不如第三种,由调用者自己申请和释放。此外该原则还有另一层意思:若使用一个指针,最好先确保它已经指向一个合法地址,否则就自己分配,不然即非法地址访问。许多程序的致命错误都是访问一个没有指向合法内存区的指针,也就是野指针,也包括空指针。

问题:内存分配 & sizeof

如果使用sizeof来计算一个指针变量,希望得到这个指针变量所分配的内存块的大小,可以吗?

char *p = NULL;

int nMemSize = 0;

p = malloc(1024);

nMemSize = sizeof(p);

答案与分析:

结果是达不到你的要求的,sizeof只能告诉你指针变量本身占用的内存大小。指针所指向的内存,如果是malloc分配的,sizeof 是无法知道的。换言之,malloc分配的内存是无法向内存管理模块进行事后查询的,当然你是可以自己编写代码来管理维护。

问题:栈内存使用

下面的程序运行会有什么问题?

char *GetString(void)

{

char p[] = "hello world";

return p;// 编译器将提出警告

}

void Test4(void)

{

char *str = NULL;

str = GetString();// str 的内容是垃圾

cout<< str << endl;

}

答案与分析:

返回栈内存,内存可能被销毁也可能不被及时销毁,但可以肯定的是出了作用域之后已被标记成可被系统使用,因此会返回乱七八糟不可知内容。当然,返回的指针的内容,应该是不变的,特殊时候是有用的,比如,可以用来探测系统内存分配规律等。

问题:内存使用相关编程规范

如果想尽可能地避免内存使用上的问题,有什么捷径吗?

答案与分析:

除非做一件从没有人做过的事情,不然都是有捷径可言的,答案那就是站在前人的肩膀上,当今各个大公司都有自己的编码规范,这些规范凝聚了许多的经验教训,有较高的使用价值,考虑到这些规范在网上流传很多,这里我就不再列举了,感兴趣的,推荐参考林锐的《高质量C/C++编程指南》。

提醒:《C语言之内存使用》最后刷新时间 2024-03-14 01:04:48,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《C语言之内存使用》该内容的真实性请自行鉴别。