关于内存 GetMemory( ) 笔试分析
1、
#include<stdio.h>
#include<string.h>
void GetMemory(char *p)
{
p=(char *)malloc(100);
}
int main()
{
char *str=“abc”; // 我们不用 NULL,用 abc 试一试
GetMemory(str);
printf("%x",str); // 这里自己添加这一句,调试发现 这里仍然是 NULL 也就是 0x0000000 所以str 仍然是空指针
strcpy(str,"Hello world"); // 执行到这一步,失败不懂啊?? why ,
printf(str);
}
| 常量区 | 栈 | ||||
| 00420028 | abc | str 自身地址 也就是&str 0012ff7c | 00420028 | ||
| str 存储的值(也就是地址00420028)也传递给 p | |||||
| &p p 自身地址 存储在 栈区 地址为 0012ff2c | 00420028 | ||||
执行 p= (char *)malloc(100);时候
| p 本身地址没有变,依旧是 &p 0012ff2c,但是存储的内容变了 | 00431c60 | ||||

懂了伐???? str 只是一个 int 型的而已,存放 'a'; 00:47:42 睡觉 !!!!
解释: GetMemory( )在调用的时候 str 进行地址传递的时候,会使得 P 指针存储的地址为 NULL 也就是 0x0000 0000
但是这里的 GetMemory 实际上是对调用函数里面的 P指针分配了内存而已,p地址随机的 这里是 0x00431ca0
GetMemory(str),实质是对p的操作,并没有对str操作,函数结束后p撤销,因此不会产生新的内存空间,str仍然是一个空指针。所以失败。
2、
char *GetMemory()
{
char p[]="Hello World";
return p;
}
void Test()
{
char * str=NULL;
str=GetMemory();
printf(str);
}
这里 调试 str=0x000000
调用函数的p指针地址为 0x0012ff18 ,然后内存里存储的是 Hello world 不能理解的是 这些 0x48 x065 0x6c 是哪来的,为什么不是 0x0012ff18 是存在堆栈里面吗?不太懂。看第三个解释,可以说明是 对的 helll world 就是放在了栈区,所以调用后释放了内存,消失了。

return p ; 这里返回了 p 的地址,也就是说 str=GetMemory()把 P的地址 0x12ff18 传给了 str ;

看起来 这一步好像是对的 ,但是只是传递的地址,而后面的“helll world ”在执行完 调用函数后被释放了,在执行下两步就知道了


看出来了 str 里面输出的 是 0 还有个箭头符号。 所以说是错的。
网上解释: 实质:当一个函数调用结束后会释放内存空间,释放它所有变量所占用的空间,所以数组空间被释放掉了,也就是说str所指向的内容不确定是什么东西。但是返回的指针指向的地址是一定的
3、
#include<stdio.h>
#include<string.h>
char *GetMemory()
{
return "hello world";
}
void main()
{
char * str=NULL;
str=GetMemory();
printf(str);
}


输出正确,为什么会这样呢? 因为是这样的:
解释: 网上的: 实质:本例打印hello world,因为返回常量区,而且并没有修改过。在上一个例子中不一定能打印hello world,因为指向的是栈区。
这里我们要 深入的学习 return 的用法了,这当然又是另外一个故事了啊!!!
4、
#include<stdio.h>
#include<string.h>
void GetMemory(char **p,int num)
{
*p=(char *)malloc(num);
}
void main()
{
char * str=NULL;
GetMemory(&str,100);
strcpy(str,"Hello");
printf(str);
| 栈 | |||||||||||
| str 自身地址 0012ff7c | NULL | ||||||||||
| p 自身地址 &p 0012ff28 | p=0012ff7c | ||||||||||
| 执行过*p=(char *)malloc(num);后,也就是为 0012ff7c 地址分配内存单元,那么 地址 0012ff7c 里面存放地址单元 | 00431c60 | ||||||||||
| 00431c60 | 那么 str 存储 | 00431c60 | |||||||||
| 地址 P指针 0012FF28 | 0012FF7C | str 0x00431ca0 |
| 存储数值 0012FF7C | *p =00431ca0 | **p = hell0 |
从图可以看出来,可以正确的打印Hello但是内存泄露了,在GetMemory()中使用了malloc申请内存,但是在最后却没有对申请的内存做任何处理,因此可能导致内存的泄露,非常危险。
不是很理解,要仔细学习 **P ,指向指针的指针的用法???? 有点犀利糊涂
09:12:50
网上理解: 之所以定义二级指针**P,不是为了使用**P表示指向的值,而是为了使用*P来存储存储值的那个单元的地址,也就是 00431ca0
一开始传参数时,存储str的单元地址赋值给P,
这样P中单元存储的就是STR的地址,
从而,*P 表示的就是STR的值
5、
#include<stdio.h>
#include<string.h>
void main()
{
char *str=(char *)malloc(100); // 分配内存
strcpy(str,"Hello"); // 复制字符串
printf(str); // 输出字符串 基本没有问题
free(str); // 指针被释放后,成了野指针,这里 不再是 NULL ,(一般来说应该不是吧)
if (str!=NULL)
{
strcpy(str,"World"); // 不是NULL ,那么继续执行,str 开始的 hello 又被 world 给覆盖了
printf(str); // 输出的 是 world
}
}
网上解释: 申请空间,拷贝字符串,输出字符串,释放空间,前四步操作都没有问题,到了if语句里的判断条件开始出错了。因为一个指针被释放了之后其内容并不是NULL,而是一个不确定的值,所以if语句是被执行的,这也是著名的“野”指针问题。
自己思考了一下,如果真的是野指针,也不一定是输出 world ,应该不太确定。
关于内存 GetMemory( ) 笔试分析的更多相关文章
- JVM内存区域异常分析
在Java虚拟机规范描述中,除程序计数器外,其他几个运行时区域都有可能发生OutOfMemoryError异常.接下来将对各区域分别进行分析介绍,内容包括触发各区域OutOfMemoryError异常 ...
- Memcached内存管理模型分析
Memcached 是一个高性能的分布式内存对象缓存系统,它通过在内存中缓存数据和对象来减少读取数据库的次数,从而减轻RDBMS的负担,提高服务的速度.提升可扩展性.本文将基于memcached1.4 ...
- Keil C动态内存管理机制分析及改进(转)
源:Keil C动态内存管理机制分析及改进 Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mem ...
- linux内存源码分析 - 零散知识点
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 直接内存回收中的等待队列 内存回收详解见linux内存源码分析 - 内存回收(整体流程),在直接内存回收过程中, ...
- linux内存源码分析 - 内存回收(整体流程)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 当linux系统内存压力就大时,就会对系统的每个压力大的zone进程内存回收,内存回收主要是针对匿名页和文 ...
- linux内存源码分析 - 内存压缩(同步关系)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 最近在看内存回收,内存回收在进行同步的一些情况非常复杂,然后就想,不会内存压缩的页面迁移过程中的同步关系也 ...
- linux内存源码分析 - 内存压缩(实现流程)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 本文章最好结合linux内存管理源码分析 - 页框分配器与linux内存源码分析 -伙伴系统(初始化和申请 ...
- linux内存源码分析 - SLUB分配器概述
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ SLUB和SLAB的区别 首先为什么要说slub分配器,内核里小内存分配一共有三种,SLAB/SLUB/SLOB ...
- linux内存源码分析 - SLAB分配器概述【转】
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 之前说了管理区页框分配器,这里我们简称为页框分配器,在页框分配器中主要是管理物理内存,将物理内存的页框分配给申请 ...
随机推荐
- Spark学习笔记(一)
1.调度 分为FIFO和FAIR两种模式 创建调度池:sc.setLocalProperty("spark.scheduler.pool", "pool6") ...
- TP自带的缓存机制
原文章出处: http://blog.163.com/liwei1987821@126/blog/static/172664928201422133218356/ 动态缓存 Cache缓存类 vie ...
- Delphi HOOK示例
本应用程序的Hook: unit UFrmMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, ...
- Maven实战(一)安装与配置
1. 简介 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. 如果你已经有十次输入同样的Ant targets来编译你的代码.jar或者w ...
- RTSP交互命令简介及过程参数描述
目录 [hide] 1 RTSP消息格式 2 简单的rtsp交互过程 3 rtsp中常用方法 3.1 OPTION 3.2 DESCRIBE 3.3 SETUP 3.4 PLAY 3.5 PAUSE ...
- CentOS7 + linux kernel 3.10.94 compile 简记
Linux kernel 一直以其开源著称,可以自己编译选择合适的模块,针对特定的系统可以有不同的编译选项 来源 此次编译的内核版本为3.10.94,从官网www.kernel.org下载而来,自己虚 ...
- Xcode 自定义代码段
看见老师敲程序时,快捷键一打,所需要的一整行代码都出来了,着实感觉到效率太高了. 看了几天,才反应过来为什么自己没有get这个方法呢,现在就整理一番,记录一下. 此处以@property(nonato ...
- Java学习-023-Properties 类 XML 配置文件读取及写入源代码
之前的几篇 Properties 文章已经讲述过了 Java 配置文件类 Properties 的基本用法,查看 JDK 的帮助文档时,也可看到在 Properties 类中还有两个方法 loadFr ...
- Java学习-010-创建文件夹源代码
此文源码主要为应用 Java 创建文件目录的源码.若有不足之处,敬请大神指正,不胜感激! 创建文件夹源代码如下所示: /** * @function 文件操作:创建文件夹.若文件夹不存在,则级联创建文 ...
- Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never diffe
class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } public class ...