前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >资深同事教我做人:堆上分配的内存,只free就完事儿了?

资深同事教我做人:堆上分配的内存,只free就完事儿了?

作者头像
用户6557940
发布2022-07-24 16:26:58
2870
发布2022-07-24 16:26:58
举报
文章被收录于专栏:Jungle笔记

malloc要和free成对使用,malloc的内存,free就完事儿了吗?

这周大部分精力是和另一位资深同事一起,修复组里新老项目上可能存在的一些安全漏洞,包括参数检查和内存释放。参数检查倒还ok,在每个函数开始出对入口参数判空。这一点老代码做得很好,所以这部分工作量很小。关键是内存的释放。

new之后,delete了吗?

malloc之后,free了吗?

准确说,是及时释放堆上动态分配的内存。作为基础知识都知道(而且书上也反复提到过),堆上动态分配的内存,诸如malloc,calloc,在使用完后要释放掉。然而在没养成良好编程习惯或者遵守编程规范的时候,往往只考虑实现功能,而没有考虑过内存泄露。

不禁回想起硕士期间开发的机器人仿真软件,为了论文需要,我专门增加了一个实时显示软件占用内存的模块。实现之后发现,在软件仿真的过程中,占用内存越来越多;反复运行仿真模块时,内存持续增加,巅峰时达到500多M。这就是因为软件里只new却不delete。那时不论是实验室还是项目公司,全部注意都在软件功能实现和炫酷上,所以压根儿不考虑内存问题。

公司里却不一样。一方面,要做成熟的产品,各方面性能需要达到最优;另一方面,资深同事review代码时会查到哪里存在内存泄漏;再者,检测工具也会查到这些内存泄漏点。

malloc后free,完整操作是什么?

按照我之前的认知,malloc分配的内存使用完毕后,应该用free释放掉,这还不算完,还应该把指针置为NULL,如下段代码:

代码语言:javascript
复制
#define BUFFER_SIZE 10
  int *buffer = (int*)malloc(BUFFER_SIZE * sizeof(int));
  for (int i = 0; i < 10; i++){
    buffer[i] = i*i;
  }
  free(buffer);
  buffer = NULL;

很多时候会忘记free,或者free了之后忘了置空。还有的时候,是可能在某个过程把一段分配的内存赋给了另一个指针,free了原来的指针后操作另一个指针会有风险。比如下段代码,buffer1和buffer2指向的是同一段内存,如果free了buffer1,其实也相当于free了buffer2了。

代码语言:javascript
复制
void print(char* title, int* buffer, int bufferSize)
{
  if (title == NULL || buffer == NULL || bufferSize <= 0){
    printf("Wrong parameters!\n");
    return;
  }
  printf("%s:\n", title);
  for (int i = 0; i < bufferSize; i++){
    printf("Address: 0x%p, Value: %d\n", buffer + i, buffer[i]);
  }
  printf("\n");
}
int  main()
{
#define BUFFER_SIZE 5
  int *buffer1 = (int*)malloc(BUFFER_SIZE * sizeof(int));
  int *buffer2 = buffer1;
  for (int i = 0; i < BUFFER_SIZE; i++){
    buffer1[i] = i*i;
  }
  print("buffer1", buffer1, BUFFER_SIZE);
  print("buffer2", buffer2, BUFFER_SIZE);
  free(buffer1);
  buffer1 = NULL;

  print("buffer2", buffer2, BUFFER_SIZE);

  system("pause");
  return 0;
}

free并且置为NULL,就完事儿了吗?

这周在开展这一项工作之前,我们先开了个会,会上主管要求我们,free之前先用memset把那段内存清零,然后再free置NULL。理由是,尽管free并置NULL了,但那段内存上的内容可能还在,有被窃取的风险

所以这周我们的操作如下段代码:

代码语言:javascript
复制
int *buffer1 = (int*)malloc(BUFFER_SIZE * sizeof(int));

  // Do something on buffer1

  memset(buffer1, 0, BUFFER_SIZE);
  free(buffer1);
buffer1 = NULL;

free只是告诉编译器,buffer指定的内存可以被重新分配了,但是这段内存上的内容呢?置0?随机值?还是保持原来的值?查了些资料,有说不变的,有说是跟具体编译器相关的,无论如何,看来主管要求的这一步,是很有必要的!

关于malloc分配内存,还有一个tip

同事在review我改的代码,提示我在为一个带有指针变量的结构体malloc一段内存后,如果这个结构体变量要作为传入的参数,在使用之前,应该先memset为0,否则里面的指针值是随机或者未知的,作为传入参数,可能有风险。对这位同事,我深表佩服!果然姜还是嫩的没那么辣!

收获满满!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Jungle笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
检测工具
域名服务检测工具(Detection Tools)提供了全面的智能化域名诊断,包括Whois、DNS生效等特性检测,同时提供SSL证书相关特性检测,保障您的域名和网站健康。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档