C语言动态内存泄露常见问题内存分配改进方法详解

目录
  • 一、例题
  • 二、2种改进方法
    • 法1:二级指针(传址调用)
    • 法2:返回指针
  • 总结

一、例题

试问该段代码能打印什么,或者不能打印什么,说出理由

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void getmemory(char*p)
{
	p = (char*)malloc(100);
}
void test()
{
	char*str = NULL;
	getmemory(str);
	strcpy(str, "hello world");
	printf("%s",str);
}
int main()
{
	test();
	return 0;
}

这段代码乍一看好像没有啥问题,test函数进去创建一个str嘛,然后str传给getmemory函数,开辟一块空间,然后hello world这字符串放进开辟的空间里,然后打印str也就是hello world嘛。
但是,上面的思路是完全错误的,代码完全无法运行,解释如下:

  • 第一:你str传到getmemory函数里,p开辟一个空间,被开辟的空间和str没有关系
    (传值调用和传址调用的区别)
  • 第二:你getmemory函数出来之后,开辟的空间没有释放掉,而且你p由于函数的结束已经销毁了,p销毁之后再也无法找到开辟的空间,造成内存泄漏

就比如p是一个警察头子,开辟的空间是卧底,只有p知道那个卧底,你现在警察头子死了,再也没法证明卧底是卧底了
也就是说p消失后,没办法再对开辟的空间进行释放,这时就会造成内存泄露

二、2种改进方法

法1:二级指针(传址调用)

代码如下(示例):

void getmemory(char**p)
{
	*p = (char*)malloc(100);//p是str地址,*p是str
}
void test()
{
	char*str = NULL;
	getmemory(&str);
	strcpy(str, "hello world");
	printf("%s",str);
	free(str);
	str = NULL;
}
int main()
{
	test();
	return 0;
}

因为之前的传值调用没法让p和str建立联系,那我们就传地址,开辟一块空间出来赋给*p
要注意的是,p是str地址嘛,*p也就是str,到这里,str掌握了新开辟空间的控制权。然后getmemory函数出来,进行strcpy和printf操作,最后不要忘记free掉原先的空间。

法2:返回指针

代码如下(示例):

char* getmemory(char*p)
{
	p = (char*)malloc(100);
	return p;
}
void test()
{
	char*str = NULL;
	str=getmemory(str);
	strcpy(str, "hello world");
	printf("%s", str);
	free(str);
	str = NULL;
}
int main()
{
	test();
	return 0;
}

因为这里是开辟了一块空间给指针p管理嘛,str和p没有建立联系,那你直接函数返回p这个指针然后赋值给str即可,随后操作和方法1一样

总结

本文介绍了动态内存分配的常见例题及两种改进方法,读者需要理解为何会发生内存泄露和传值与传址调用的区别就可以熟练解决这类问题。以上,祝读者学习愉快~希望大家以后多多支持我们!

(0)

相关推荐

  • c语言内存泄露示例解析

    正确的内存管理的重要性存在内存错误的 C 和 C++ 程序会导致各种问题.如果它们泄漏内存,则运行速度会逐渐变慢,并最终停止运行:如果覆盖内存,则会变得非常脆弱,很容易受到恶意用户的攻击.从 1988 年著名的莫里斯蠕虫 攻击到有关 Flash Player 和其他关键的零售级程序的最新安全警报都与缓冲区溢出有关:"大多数计算机安全漏洞都是缓冲区溢出",Rodney Bates 在 2004 年写道. 在可以使用 C 或 C++ 的地方,也广泛支持使用其他许多通用语言(如 Java™.

  • 深入解析C语言中的内存分配相关问题

    C内存分配区域 程序代码区 存放函数体的二进制代码 全局数据区 全局变量和静态变量的存储是放在一起的.初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域.常量数据存放在另一个区域里.这些数据在程序结束后由系统释放.我们所说的BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称 栈区 由编译器自动分配释放,存放函数的参数值,局部变量的值等.其操作方式类似

  • C语言 动态内存分配的详解及实例

    1. 动态内存分配的意义 (1)C 语言中的一切操作都是基于内存的. (2)变量和数组都是内存的别名. ①内存分配由编译器在编译期间决定 ②定义数组的时候必须指定数组长度 ③数组长度是在编译期就必须确定的 (3)但是程序运行的过程中,可能需要使用一些额外的内存空间 2. malloc 和 free 函数 (1)malloc 和 free 用于执行动态内存分配的释放 (2)malloc 所分配的是一块连续的内存 (3)malloc 以字节为单位,并且返回值不带任何的类型信息:void* mallo

  • c语言内存泄漏严重的解决方法

    摘要:通过介绍内存泄漏问题原理及检视方法,希望后续能够从编码检视环节就杜绝内存泄漏导致的网上问题发生. 1. 前言 最近部门不同产品接连出现内存泄漏导致的网上问题,具体表现为单板在现网运行数月以后,因为内存耗尽而导致单板复位现象.一方面,内存泄漏问题属于低级错误,此类问题遗漏到现网,影响很坏:另一方面,由于内存泄漏问题很可能导致单板运行固定时间以后就复位,只能通过批量升级才能解决,实际影响也很恶劣.同时,接连出现此类问题,尤其是其中一例问题还是我们老员工修改引入,说明我们不少员工对内存泄漏问题认

  • C语言动态内存泄露常见问题内存分配改进方法详解

    目录 一.例题 二.2种改进方法 法1:二级指针(传址调用) 法2:返回指针 总结 一.例题 试问该段代码能打印什么,或者不能打印什么,说出理由 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib.h> void getmemory(char*p) { p = (char*)malloc(100); } void test() { char*str =

  • LyScript实现内存交换与差异对比的方法详解

    目录 内存区域交换 内存区域对比 内存与磁盘机器码比较 内存ASCII码解析 内存特征码匹配 LyScript 针对内存读写函数的封装功能并不多,只提供了内存读取和内存写入函数的封装,本篇文章将继续对API进行封装,实现一些在软件逆向分析中非常实用的功能,例如内存交换,内存区域对比,磁盘与内存镜像比较,特征码检索等功能. LyScript项目地址:https://github.com/lyshark/LyScript 内存区域交换 实现被加载程序内特定一块内存区域的交换,该方法实现原理就是两个变

  • C语言实现短字符串压缩的三种方法详解

    目录 前言 一.通用算法的短字符压缩 二.短字符串压缩 (1)Smaz (2)Shoco (3)Unisox2 三.总结 前言 上一篇探索了LZ4的压缩和解压性能,以及对LZ4和ZSTD的压缩.解压性能进行了横向对比.文末的最后也给了一个彩蛋:任意长度的字符串都可以被ZSTD.LZ4之类的压缩算压缩得很好吗? 本篇我们就来一探究竟. 一.通用算法的短字符压缩 开门见山,我们使用一段比较短的文本:Narrator: It is raining today. So, Peppa and George

  • JavaScript动态检测密码强度原理及实现方法详解

    本文实例讲述了JavaScript动态检测密码强度原理及实现方法.分享给大家供大家参考,具体如下: 在注册账户,设置密码时,会出现密码强度动态检测,网上看了一些帖子,大多只写了具体的实现过程,而没有对原理的分析过程.下面着重讲一下其原理. 原理分析 通常实现密码强度动态判断有两种方案实现: 正则.但其效率低一点,难度也大一些. 字符串,函数和运算符. 这里用第二种方案,但是如何判断一个密码串是强还是弱呢? 一般我们的密码会设置为数字.字母(大小写).特殊符号三类. 强:密码串包含其中三种或以上

  • 解析Android获取系统cpu信息,内存,版本,电量等信息的方法详解

    Android获取系统cpu信息,内存,版本,电量等信息 1.CPU频率,CPU信息:/proc/cpuinfo和/proc/stat 通过读取文件/proc/cpuinfo系统CPU的类型等多种信息.读取/proc/stat 所有CPU活动的信息来计算CPU使用率 下面我们就来讲讲如何通过代码来获取CPU频率: 复制代码 代码如下: package com.orange.cpu; import java.io.BufferedReader;import java.io.FileNotFound

  • DHCP:解析开发板上动态获取ip的2种实现方法详解

    DHCP动态主机设置协议(Dynamic Host Configuration Protocol, DHCP)是一个局域网的网络协议,使用UDP协议工作,主要有两个用途:1.给内部网络或网络服务供应商自动分配IP地址2.给用户给内部网络管理员作为对所有计算机作中央管理的手段. 方法一:dhclient    1.下载    https://www.isc.org/software/dhcp/2.解压    tar-zxvf dhcp-3.1.3.tar.gz3.配置    cddhcp-3.1.

  • mysql存储过程 在动态SQL内获取返回值的方法详解

    MySql通用分页存储过程过程参数 复制代码 代码如下: p_cloumns varchar(500),p_tables varchar(100),p_where varchar(4000),p_order varchar(100),p_pageindex int,p_pagesize int,out p_recordcount int,out p_pagecount int $:begin    declare v_sqlcounts varchar(4000);    declare v_s

  • Go语言读取,设置Cookie及设置cookie过期方法详解

    Cookie用来解决http协议无状态的问题. 首先,在服务端生成Cookie,然后在http响应header中设置Set-Cookie字段,客户端会读取到Set-Cookie字段后,会将cookie信息存储起来,下次继续访问服务端时,会在http请求中设置Cookie字段并发送给服务端,服务端可以解析这个Cookie字段,从而知道这个客户端之前已经和自己有过会话(上下文),然后再执行相应的逻辑代码. Cookie分为两种类型:session cookie和persistent cookie.

  • C++ 操作系统内存分配算法的实现详解

    目录 一.实验目的 二.实验内容 三.实验要求 四.代码实现 五.测试样例 一.实验目的 通过本实验帮助学生理解在动态分区管理方式下应怎样实现主存空间的分配和回收. 二.实验内容 在动态分区管理方式下采用不同的分配算法实现主存分配和实现主存回收. 三.实验要求 (1)可变分区方式是按作业需要的主存空间大小来分割分区的.当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业:若无,则作业不能装入.随着作业的装入.撤离.主存空间被分成许多个分区,有

  • 关于Java变量的声明、内存分配及初始化详解

    实例如下: class Person { String name; int age; void talk() { System.out.println("我是: "+name+", 今年: "+age+"岁"); } } public class TestJava2_1 { public static void main(String args[]) { Person p; if (p == null) { p = new Person(); }

随机推荐