动态内存中关于GetMemory函数的几道问题

编程入门 行业动态 更新时间:2024-10-20 05:41:01

动态内存中关于GetMemory函数的<a href=https://www.elefans.com/category/jswz/34/1759029.html style=几道问题"/>

动态内存中关于GetMemory函数的几道问题

学习完动态管理内存这部分内容之后,我们对它在实际问题中的应用可能还不是很了解,通过这几个例子我们来进一步巩固动态内存的相关知识。


目录

1.非法访问以及内存泄漏问题

1.1错误实例

1.2正确代码

2.返回栈空间地址,非法访问问题

2.1错误示例

2.2正确代码

3.野指针被使用的问题

3.1错误代码

3.2正确代码


1.非法访问以及内存泄漏问题

1.1错误实例

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>void GetMemory(char* p)
{p = (char*)malloc(sizeof(char) * 100);if (p == NULL){perror("malloc");return ;}
}
void Test(void)
{char* str = NULL;GetMemory(str);strcpy(str, "hello world!");printf(str);
}
int main()
{Test();return 0;
}

我们会发现这个代码运行不出来

为什么会这样,我们来仔细分析一下:

这个代码存在两个问题

1.调用函数GetMemory时,我们传入str,这里传的是str本身,属于值传递,指针p得到的是str的值NULL,使用malloc函数后,假设开辟好的空间的首地址为0f12ff40,p指向这块空间的首地址,但是这与str无关,p是str的一份临时拷贝,有自己独立的空间,str的值依然为NULL,当GetMemory函数运行结束时,p被销毁,空间回收,malloc开辟好的空间我们无法得知在哪,我们没有机会释放malloc开辟的空间,存在内存泄漏

2.同时,我们在销毁了指针p后,依旧使用这块空间,对它进行strcpy,这是存在非法访问

1.2正确代码

我们有两种改正方法

1.第一种:我们以前学到过,修改一级指针要用二级指针,即用二级指针来接收一级指针的地址,同时,使用完这块空间后要进行释放

//正确代码
// 
//第一种改正
void GetMemory(char** p)
{*p = (char*)malloc(sizeof(char) * 100);if (*p == NULL){perror("malloc");return ;}
}
void Test(void)
{char* str = NULL;GetMemory(&str);//我们在这里传入一级指针的地址,用二级指针来接收strcpy(str, "hello world!");printf(str);//使用完之后我们要进行空间释放free(str);str = NULL;
}
int main()
{Test();return 0;
}

2.第二种:我们给GetMemory函数一个返回值,这样执行这个函数结束时,p指针不会被销毁,同时,使用完这块空间后要进行释放

//第二种改正
char* GetMemory(char* p)
{p = (char*)malloc(sizeof(char) * 100);if (p == NULL){perror("malloc");return 1;}return p;
}
void Test(void)
{char* str = NULL;str=GetMemory(str);//我们用指针str来接收函数返回值strcpy(str, "hello world!");printf(str);//使用完之后我们要进行空间释放free(str);str = NULL;
}
int main()
{Test();return 0;
}

如果认真看了我们写的代码,你可能会疑惑printf(str)这种输出函数的写法真的正确吗,我们下面来分析一下:

int main()
{char* str = "abcdef";//这里str指向的是字符串的首地址也就是a的地址printf("%s\n", str);printf("abcdef\n");//这里打印时,传给printf函数的其实是字符串首地址a的地址printf(str);//所以我们这种写法是完全正确的,str中放的是a的地址,printf函数//接收的也是a的地址return 0;
}

2.返回栈空间地址,非法访问问题

2.1错误示例

char* GetMemory(void)
{char p[] = "hello world!";return p;//返回栈空间地址的问题
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}
int main()
{Test();return 0;
}

我们分析一下这个代码:

p数组中存放“hello world!\0”,return p时,返回首字符的地址即h的地址,但同时返回这个首地址之后也释放了这块空间,归还了操作系统,我们没有权限使用这块空间,但是str接收了这块空间还打印了str,属于非法访问,越界访问

2.2正确代码

这种也有两种改法:

1.想要使用这块空间,我们需要把数组p变为指针p,这样就能找到这块空间,打印完整的字符串

//正确代码char* GetMemory(void)
{char* p = "hello world!";return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}
int main()
{Test();return 0;
}

2.把数组p变成静态区的变量,那么这块空间就不会被释放掉,里面存入的字符串也可以被打印

//第二种char* GetMemory(void)
{static char p[] = "hello world!";//存入静态区return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}
int main()
{Test();return 0;
}

3.野指针被使用的问题

3.1错误代码

//野指针被使用void Test(void)
{char* str = (char*)malloc(sizeof(char) * 100);if (str == NULL){perror("malloc");return;}strcpy(str, "hello");printf(str);free(str);if (str != NULL){strcpy(str, "world!");printf(str);}
}
int main()
{Test();return 0;
}

我们查看代码,发现str被free后依旧被使用,此时,str是一个野指针,str指向的这块空间被释放,但是我们在释放后还想通过str这个指针来使用这块空间打印world!,这就形成了非法访问,我们以前就说过,虽然可以打印出来,但这是违法的,不安全

3.2正确代码

解决这个问题我们也有两种方法:

1.我们在free(str)后,应该把str主动置为NULL,确保不会形成野指针

//正确代码
void Test(void)
{char* str = (char*)malloc(sizeof(char) * 100);if (str == NULL){perror("malloc");return;}strcpy(str, "hello");printf(str);free(str);str = NULL;//想要使用的话可以在重新开辟一块空间if (str != NULL){strcpy(str, "world!");printf(str);}
}
int main()
{Test();return 0;
}

2.在整体使用完之后再释放这块空间


void Test(void)
{char* str = (char*)malloc(sizeof(char) * 100);if (str == NULL){perror("malloc");return;}strcpy(str, "hello");printf(str);strcpy(str, " world!");printf(str);//使用完之后在释放free(str);str = NULL;
}
int main()
{Test();return 0;
}


这就是我们应用动态开辟内存函数常遇到的问题,其实,只要大家书写时细心,这些问题是可以避免的,本期分享就到这里,大家下期再见!!!

更多推荐

动态内存中关于GetMemory函数的几道问题

本文发布于:2023-12-01 18:25:26,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1651700.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:几道   函数   内存   动态   GetMemory

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!