越界访问
首先我们上一个代码,看看这个的代码的问题
这个代码的问题显而易见 ,就是在循环里面,产生了越界访问的问题,这里你开辟了10个整形空间,但是从0-10一共是11个整形空间。导致访问不合法的空间,从而导致内存泄露,内存泄露会导致,这个内存一直使用,逐步积累,从而导致内存呗占满。
——————————————————————————————————————————
free只能释放动态的空间
上面的重点我们说的很清楚,为什么不能让指针移动
这里我们写上一个代码
指针移动之后 你指的是静态的空间,我们的是什么,我们的函数的动态内存空间的管理。
这里释放的是 p之后的空间
这里 的p不再是动态申请的起始位置
指针跑远了 也就是不指向释放空间了
所以才需要*(p+i)=i+1;
———————————————————————————————————————————
重复释放
也就是两个free
也就不行的
但是你要是 释放之后指向为空指针 那就没有什么问题
重复释放会导致的问题:
1. **不可预知的行为**:
当你重复释放同一块内存时,那个内存区域可能已经被重新分配给了其他用途。如果你再次试图访问它,你可能会读取到未定义的数据,或者更糟糕的是,破坏了其他部分的程序。
2. **内存冲突**:
如果你在释放内存之后又重新分配了相同的大小,并且期望得到相同的内存地址,这是不确定的。每次调用`malloc`或`realloc`都可能返回一个新的内存地址。因此,即使你的代码在逻辑上看起来可以工作,这也是依赖于实现的,并且不应该依赖这种行为。
3. **内存泄漏**:
虽然重复释放内存不会直接导致内存泄漏(因为内存已经被释放),但这通常意味着管理内存不当,可能会导致其他内存泄漏问题。
4. **性能问题**:
在某些情况下,操作系统和内存管理器可能会对重复释放小块内存的行为进行优化,如通过释放和立即重新分配来减少碎片。然而,这取决于具体的实现和配置,不应该依赖于此。
为了避免这些问题,你应该确保每个`malloc`或`realloc`调用都有一个对应的`free`调用,并且只释放一次。一个常用的做法是,在每次调用`malloc`或`realloc`时,都记录下返回的指针,然后在`free`中检查是否是同一个指针,避免重复释放。
———————————————————————————————————————————
忘记释放
导致内存泄露的问题
内存是一种资源 当申请之后不用的时候是需要回收的
其实malloc calloc realloc 申请的内促 如果不想使用 可以使用free释放
如果没有使用free来释放当程序运行结束的时候 也会由操作系统回收的
也就是 一直不退出的话 那个内存别人也用不上
所以 如果申请不释放的话 必须要进行说明
1.谁申请是谁释放------------------malloc free成对出现 --不然就会导致内存泄露的问题 --即使成对出现 也会导致泄露问题
就比如,这里也就是出问题了 即使malloc和free成对出现 也是出现问题了
2.如果不释放 也就是需要告诉使用的人,记得释放
———————————————————————————————————————————
传值调用错题详解(重点)
首先我们来看这个错误代码
首先我们看代码逻辑,首先main函数调用test,test接收的是void类型,设置一个指针变量,指向null,传递给get函数,也就是传递一个空指针给getmemory函数,这个函数接收了,然后进行运算。
接下来我们进行分析代码的错误逻辑。
为什么不取地址是错误的呢,
- 传递地址(指针的指针): 当你传递
&str
(str
的地址)给函数时,你是在告诉函数你想要操作的是str
变量的内存地址本身。这允许函数直接修改str
变量的值,或者使用str
变量的地址进行其他操作。 - 传递指针(不取地址): 当你传递
str
(指向char
的指针)给函数时,你是在告诉函数你想要操作的是str
指向的字符串。函数可以通过str
指针访问和修改字符串的内容,但不会直接修改str
指针本身的值。
这样会导致什么情况呢,就是内存销毁的问题,你这个函数传递的时候,传递的是指针,不是指针的地址。那么此时就会产生一种情况那就是,getmemory函数运算结束,这个函数进行了销毁。
因为他调用结束之后,函数会进行销毁,strcpy函数想拷贝到开辟的空间里面,OK!找不到空间了,因为进行了销毁。
什么意思呢,可以理解为,
张三,有一天忙碌完,不想回家了,在公司楼下开了个酒店住进去了,哎,很不错,告诉李四,我住的209房间特别好,你有空可以去试试。第二天李四也累了,那我也去了,我到地方我就记得209房间,但是张三的209房间已经退房了,那我肯定进不去,我非得进去,那就被保安打一顿。
你这里也是这样,你这里 想拷贝字符创,那可以没问题。关键点在于你这里传递的是数值,他不是地址,那数值的话,函数创建了,然后运行结束进行销毁。你自然找不到房间号。你这里要是传递的是空间的地址,那我可以直接去你的地址进行操作拷贝,你也不需要进行返回什么的,哪怕进行销毁了,那也没事。
1.因为这里传参传递的是数值,函数返回的时候进行了函数的销毁,从而导致非法访问
这里的意思 应该是把100个字节放到str里面去 但是传值调用是不行的 会导致有问题
正确的处理应该是什么呢
我们可以把str取地址,传参传的是地址,然后因为本身str已经是指针,我们采取用二级指针的方式进行接收,也就是指向的是指针的地址,
修改为正确代码1
此时就可以完成任务了
修改为正确代码2
当然 不喜欢二级指针 也可以进行数值的接受 也就是char*
找个数值进行接收,找个数值进行接收,那就是有返回类型,我们采取的返回类型是char*类型,因为这里是拷贝字符串。接收返回值也是一样的。
提示一下,所以其实不传参也是可以的
图解