动态内存管理笔试题

devtools/2024/10/9 3:28:43/

目录

  • 1.第一题
    • 1.1如何修改
  • 2.第二题
    • 2.1题想
    • 2.2深刻理解
  • 3.第三题
  • 4.第四题

1.第一题

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

请问运⾏Test 函数会有什么样的结果?

我们来分析一下这个程序:
首先我们创建一个指针变量str,指向NULL,将其做参数传给函数GetMemory,进入函数;
我们在函数中申请100字节的空间,首地址给形参p,结束函数的调用;
出函数后,我们销毁了形参p;
但是str还是指向NULL,strcpy函数必会对str进行解引用,不能对空指针进行解引用,所以会崩溃;
在这里插入图片描述

1.1如何修改

这里我们可以有两种修改方法;
第一种:
str传进这个函数的方式是传值调用,并不会影响到str的值,所以我们可以传进str的地址:

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

运行结果:
在这里插入图片描述
第二种:
我们也可以将修改后的指针返回出函数:

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

运行结果:
在这里插入图片描述

2.第二题

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

请问运⾏Test 函数会有什么样的结果?

我们先来分析一下这个函数:
在这里插入图片描述
这题其实不难,等GetmMemory函数返回后,使用str指针去访问p数组,就是非法访问,因为p数组的内存已经还给了操作系统,所以,str是野指针;
运行出来结果并不是我们所想的hello world:
在这里插入图片描述

2.1题想

我们通过此题,我们发现,函数是不能返回栈空间的地址

2.2深刻理解

但是有人可能会甩出这样的代码:

int* test()
{int n = 10;return &n;
}int main()
{int* p = test();printf("%d\n", *p);
}

运行结果:
在这里插入图片描述
这不也是打印出结果了吗?
这里偶然的成功并不是长久之计;因为这里p指向的内存并没有被覆盖,所以我们可以打印出,如果我们在打印前加上一个其他的打印:

int* test()
{int n = 10;return &n;
}int main()
{int* p = test();printf("hehe\n");printf("%d\n", *p);
}

那运行结果就大差人意了:
在这里插入图片描述
到这你一定对这题有了更深刻的理解了;

3.第三题

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

请问运⾏Test 函数会有什么样的结果?

这个代码有点像第一题的优化方案,但是有没有什么问题呢?

其实这个代码已经很完善了,但是没有free,所以我们应该这样改:

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

所以各位在申请空间后一定要记得归还,不然可能会出问题;

4.第四题

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

请问运⾏Test 函数会有什么样的结果?

这题其实是考察我们free函数是否可以将指针置空,我们前面在讲动态内存管理的时候我们就知道了,free函数并不会给指针置空;所以也会打印出world:
在这里插入图片描述

此题告诉我们free函数并不会置空,所以我们应当添上;


http://www.ppmy.cn/devtools/122414.html

相关文章

算法题总结(七)——栈与队列

1、栈常用操作 &#xff08;1&#xff09;栈定义 Stack<Integer> stack new Stack<Integer>();&#xff08;2&#xff09;栈操作 .栈是否为空 isEmpty(); .查询栈顶元素&#xff0c;不改变栈 peek(); .弹出栈顶元素&#xff0c;改变栈 pop(); .压入栈顶 push(); …

Vue.js 组件开发详解

在现代前端开发中&#xff0c;Vue.js 是一款非常流行的框架&#xff0c;以其简洁的 API 和灵活的组件化体系深受开发者喜爱。在 Vue.js 中&#xff0c;组件&#xff08;Component&#xff09;是核心概念之一&#xff0c;帮助开发者构建复杂而高效的用户界面。本文将详细讲解 Vu…

Ceph RocksDB 深度调优

介绍 调优 Ceph 可能是一项艰巨的挑战。在 Ceph、RocksDB 和 Linux 内核之间&#xff0c;实际上有数以千计的选项可以进行调整以提高存储性能和效率。由于涉及的复杂性&#xff0c;比较优的配置通常分散在博客文章或邮件列表中&#xff0c;但是往往都没有说明这些设置的实际作…

git创建新分支

git创建新分支 1.先在gitLab上New branch. 2.本地右键git小乌 - /切换/检出-创建新分支&#xff0c;分支名称和上一步创建的一样。 最后记得改个文件提交下&#xff0c;看看gitLab上是否提交成功。

数据和算力共享

数据和算力共享 针对数字化应用实践中需要在不同的物理域和信息域中进行数据的访问交换以及共享计算等需求,本文分析了在数据平台、数据集成系统以及信息交换系统中存在的问题。 在基于联邦学习的基础上,提出一种跨域数据计算共享系统,能够同时共享数据和计算资源,并支持在线…

和饺子店老板的闲聊,尽显人间清醒智慧

经常去的一家手工饺子店&#xff0c;味道不错&#xff0c;服务态度挺好。 前天过去&#xff0c;听老板说前阵子招了一个员工&#xff0c;员工估计在大饭店干过&#xff0c;对这种小饺子店看不上&#xff0c;到处挑刺。 最主要的是&#xff0c;当着顾客的面和老板对着干&#…

java目录总结

java----Random-CSDN博客 java----数组-CSDN博客 java数组_int rnumber r.next(1, 7);-CSDN博客 java---函数方法-CSDN博客 java----ArrayList-CSDN博客 java---日期-CSDN博客 java---Set,Date-CSDN博客 java---Collections-CSDN博客 java-----Map-CSDN博客 java----…

操作系统中的进程管理详细介绍——进程的调度与通信

进程管理是操作系统中至关重要的功能之一&#xff0c;它负责协调和管理计算机系统中运行的所有进程。以下是对进程管理各个方面的详细介绍&#xff1a; 1. 进程调度 进程调度是操作系统决定哪个进程在何时运行的过程&#xff0c;目的是最大化CPU的利用率和系统的整体性能。常…