【经典笔试题】动态内存管理

news/2024/11/19 18:46:02/

test1:

void GetMemory(char* p)
{p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);
}int main()
{Test();return 0;
}

请问执行上面代码,会出现什么结果?

解析:运行该段代码时,程序会崩溃

答案:调用Test函数时,在Test函数内部又调用Getmemory函数,即使在Getmemory函数内部申请空间,返回的该空间的起始地址给p,然而p并未返回,str仍为NULL。拷贝 "hello world"到str内部,将会导致程序崩溃。

改正:可以将p申请的空间返回。

test2

char* GetMemory(void)
{char p[] = "hello world";return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}int main()
{Test();return 0;
}

请问执行上面代码,会出现什么结果?

解析:运行该程序时,可能会出现乱码。

这是因为在调用GetMemory函数时,p是一个数组,在栈空间上申请内存,即使返回p,用str指针来接收,此时str指针指向了p的地址,但是在调用Getmemory完成后,p所在的空间会被释放,所以str指向的空间是一块未知的空间,使用该空间也造成了非法访问,空间内的内容我们是不知道的。

改正:可以将char p[] 改成char *p, 这样创建的空间就算再常量区,而不是再栈区,出了该函数也不会再销毁该空间。

test3

void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);
}int main()
{Test();return 0;
}

请问执行上面代码,会出现什么结果?

解析: 运行该段代码,会打印hello。

就算能运行hello,但是在使用完申请的空间后,并没有释放申请的空间,会造成内存泄露

改正:free(str); str = NULL;

test4


void Test(void)
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str);if (str != NULL){strcpy(str, "world");printf(str);}
}int main()
{Test();return 0;
}

请问执行上面代码,会出现什么结果?

解析:输出world。

然而,即使会打印world,str是在使用一块不属于自己的空间,因为在第一次拷贝hello之后,对str指向的空间进行了释放,该空间不再属于str,str已经成为野指针。但是str仍然存着这块释放掉的空间的起始地址,所以进入判断语句的时候,该语句不再起到能够阻止str进入的效果,随后str使用的空间是属于操作系统的空间,非法使用空间会有很大的安全隐患。

改正:在free(str);后面加上 str = NULL;

最后:附上c内存分配的几个主要区域。


http://www.ppmy.cn/news/12599.html

相关文章

一文入门 —— JavaScript

系列文章目录 文章目录 系列文章目录前言一、JavaScript是什么?二、使用方法三、基本语法四、DOM对象五、BOM对象其它资料前言 本系列教程目录与说明可查看这篇文章:C/C++教程 本章主要介绍前端三大基石之一的JavaScript 一、JavaScript是什么? 它并不像HTML、CSS这样看…

opencv的mat openvino的tensor libtorch的tensor

opencv的mat 对于矩阵数据,在opencv里面是通过使用mat这个数据结构来实现的,我觉得这个数据结构本身设计是用来做图片的存储,所以很多的教程都是关于三维矩阵的(其中一个维度是channel),关于三维矩阵的定义…

JUC面试(一)——JUCJMMvolatile 1.0

JUC&JMM JMM JUC(java.util.concurrent) 进程和线程 进程:后台运行的程序(我们打开的一个软件,就是进程),资源分配单位线程:轻量级的进程,并且一个进程包含多个线程…

LeetCode 300. 最长递增子序列

🌈🌈😄😄 欢迎来到茶色岛独家岛屿,本期将为大家揭晓LeetCode 300. 最长递增子序列,做好准备了么,那么开始吧。 🌲🌲🐴🐴 一、题目名称 LeetCo…

已解决Python读取20GB超大文件内存溢出报错MemoryError

已解决Python读取20GB超大文件内存溢出报错MemoryError 文章目录报错问题报错翻译报错原因解决方法1解决方法2(推荐使用)帮忙解决报错问题 日常数据分析工作中,难免碰到数据量特别大的情况,动不动就2、3千万行,如果…

Kruskal重构树学习笔记(C++)

Kruskal重构树学习笔记 提示: 学习Kruskal重构树之前建议先了解一下Kruskal算法,虽然不了解这个影响不会很大 但一定要了解一下并查集的算法 接下来如果想要应用Kruskal重构树,一定要了解一下LCA算法 什么是Kruskal重构树 这里先简单说…

Linux进程间通信

文章目录进程间通信介绍进程间通信的概念进程间通信的目的进程间通信的本质进程间通信的分类管道什么是管道匿名管道匿名管道的原理pipe函数匿名管道使用步骤管道读写规则管道的特点管道的四种特殊情况管道的大小命名管道命名管道的原理使用命令创建命名管道创建一个命名管道命…

第一个python程序

我们将看一下如何用Python编写运行一个传统的“Hello World”程序。通过它,你将学会如何编写、保存和运行Python程序。 有两种使用Python运行你的程序的方式——使用交互式的带提示符的解释器或使用源文件。 1.使用带提示符的解释器 在命令行的shell提示符下键入python,启动解释…