- 积分
- 886
- 帖子
- 192
|
这里我和年夜家一起探讨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++编程指南》。
|
|