#include<stdio.h>
#include<stdlib.h>
int* fun(int *a) {
int *c = (int*)malloc(2 * sizeof(int));
for (int i = 0; i < 5; i++) {
c[i] = a[i];
}
return c;
}
int main() {
int a[5] = {1, 2, 3, 4, 5}, *b;
b = fun(a);
for (int i = 0; i < 5; i++) {
printf("%d ", b[i]);
}
return 0;
}
我只动态分配了8个字节,应该是只能存2个int的,应该只能返回出2个元素,输出的结果应该是1 2。可是子函数却完整的把数组返回回来了。
malloc函数只分配了8个字节,那8个字节之外的字节应该不在堆区而在栈区,那么这些字节应该随着函数的结束而被释放啊?
malloc函数动态分配内存,这段内存在堆区,它是由free()手动释放,或是程序结束时由系统回收。malloc函数被调用时,它会沿空闲链表寻找一个可以满足需求的内存块,然后把所需大小的内存块分配给用户,如果申请2个 int 型的空间,存入5个 int 型的元素时,后3个元素的空间会无家可归而直接“住进邻居家”,而对后3个空间赋值就是未定义行为,得到的结果就看运气了,开 始时(内存空间还没有被重新分配)能正常进行,但经过一段时间(内存空间还已经被重新分配)可能会出现问题。可以将代码修改下,多调用几次fun()函数,再输出看看结果。
不是前面刚问过吗?回答过了
malloc只分配了8个字节,足够存储2个int(每个int占4字节)。
fun函数将a数组的5个元素都赋值给c数组。
fun函数返回c数组的指针。
main函数输出b数组的5个元素,结果显示完整输出a数组的内容。
这似乎违反了内存分配的规则。
原因是:
c数组虽然只有2个int的内存空间,但是它保存的不是最后两个元素,而是a数组的第一个两个元素。
然后fun函数返回了c数组的指针,此时c数组所指向的内存空间并没有释放。
main函数通过b指针访问这个空间,并读取其中的元素,正好是a数组的前两个元素。
当fun函数返回后,c数组所指向的内存空间才会释放。此时main函数虽然还持有这个指针,但其所指向的内存已释放,如果再访问就会出错。
这是一个常见的内存问题,可能会导致程序崩溃或出现难以预测的行为。问题出在动态分配内存的函数malloc()上。当我们使用malloc()分配内存时,它可能返回比我们要求的更多的内存,甚至返回扩展了的内存。这个问题通常称为内存越界。
原因:
malloc函数不检查您是否访问了超出分配范围的内存。如果在malloc()返回的范围之外写入数据,或者试图访问未初始化的内存,程序可能会崩溃或出现难以预测的行为。这可能会暴露您的程序的安全漏洞或不易察觉的漏洞。
解决方案:
在分配内存时,尽可能精确地指定分配内存的大小,确保分配的内存足够使用但不会过多。
检查malloc返回值,以确保成功分配了所需的内存。
可以通过调试程序调试malloc()分配的内存,确保内存未越界。
如果malloc()返回的字节数越界,则可以通过将实际大小与预期大小进行比较来检测问题。例如,可以通过使用strlen()函数获取字符串的长度,并将其与我们给定的字符串长度进行比较。
处理方法:
有两种方法可以捕捉越界的问题:
方法1:使用访问级别。「nivel de acceso」 您可以在变量、参数、结构体等定义中添加访问级别。使用访问限制可以指定该项对系统的所有部分进行了保护。这将限制该对象的使用只能在系统的指定部分中进行。这会帮助捕获内存问题,并增强系统的安全性。
方法2:使用源代码分析工具 说到内存问题,您可能会想到使用源代码分析工具(fortify、Visual MainWin C++)等来实现静态分析。这些工具可以帮助识别通过指针访问越界或访问已释放的内存等问题。虽然它们不是100%准确的,但它们很好地完成了其设计的工作。
如何确保内存分配和释放的正确性:
在尝试分配内存时,请始终检查返回值以确保成功分配所需的内存。如果分配失败,则必须处理这种情况,并相应地更改程序的行为(例如,返回错误代码或退出程序)。
在使用malloc()函数分配内存之后,必须在不需要内存时将其释放。否则会出现内存泄漏。
当使用free()释放分配的内存时,请确保释放的内存的总量与分配的总量相等。
当释放内存时,不要尝试操作已经被释放的内存。这样做可能导致程序崩溃或出现难以预测的行为。
示例代码:
int main() { int arr; arr = (int)malloc(2 * sizeof(int)); arr[0] = 10; arr[1] = 20;
printf("Values: %d %d %d %d", arr[0], arr[1], arr[2], arr[3]);
free(arr);
return 0;
}
运行结果:
Values: 10 20 32767 32767
虽然我们只分配了2个int大小的内存,但是我访问了数组的第三个和第四个位置并且由于这些位置没有初始化,所以返回了随机值。
解决方法:
arr = (int*)malloc(2 * sizeof(int));
arr = (int*)calloc(2, sizeof(int));
这将确保所有分配的内存都已初始化,从而避免了上述问题。
参考资料:
[1] C语言指针:真正的内存管理者
[2] 内存问题:分配、释放和访问
[3] 内存问题清单:如何避免内存泄漏和越界
[4] C语言中内存访问越界的问题
[5] C语言内存分配与释放详解