指针空间的申请与释放

一、malloc()和free()的基本概念以及基本用法:
1、函数原型及说明:
void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
关于分配失败的原因,应该有多种,比如说空间不足就是一种。

char *Ptr = NULL; Ptr = (char *)malloc(100 * sizeof(char)); if (NULL == Ptr) { exit (1); } gets(Ptr);
void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
free(Ptr); Ptr = NULL; // code...

free()到底释放了什么?这个问题比较简单,其实我是想和第二大部分的题目相呼应而已!哈哈!free()释放的是指针指向的内存!注意!释放的是内存,不是指针!这点非常非常重要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,前面我已经说过了,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。非常重要啊这一点! 就是这样!当然,具体情况要具体分析以及具体解决。比如说,你定义了一个指针,在一个函数里申请了一块内存然后通过函数返回传递给这个指针,那么也许释放这块内存这项工作就应该留给其他函数了。
3、关于函数使用需要注意的一些地方:
A、申请了内存空间后,必须检查是否分配成功。
B、当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。
C、这两个函数应该是配对。如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会
出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。
D、虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一
些编译器的检查。
好了!最基础的东西大概这么说!现在进入第二部分:

二、malloc()到底从哪里得来了内存空间:
1、malloc()到底从哪里得到了内存空间?答案是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。就是这样!
说到这里,不得不另外插入一个小话题,相信大家也知道是什么话题了。什么是堆?说到堆,又忍不住说到了栈!什么是栈?下面就另外开个小部分专门而又简单地说一下这个题外话:
2、什么是堆:堆是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程 初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
什么是栈:栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
以上的概念描述是标准的描述,不过有个别语句被我删除,不知道因为这样而变得不标准了^_^.
通过上面对概念的描述,可以知道:
栈是由编译器自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据结构中的栈。
堆一般由程序员分配释放,若不释放,程序结束时可能由OS回收。注意这里说是可能,并非一定。所以我想再强调一次,记得要释放!

一、定义指针的时候一定要初始化。

变量定义的时候给变量初始化,这是保证不出错的一个很好的习惯。尤其是在指针的使用上,如果我们没有给指针初始化,就会出现野指针,该指针的指向并不是我们所希望的,一旦错误的释放了这个指针,就会发生内存的访问。那么如何初始化指针变量呢,一般有以下几种方法:
1、初始化空指针
int* pInteger=NULL;
2、用已有的变量初始化
int length=5;
int* pInteger=&length;
3、用内存分配函数给指针分配空间
int* pInteger=(int*)malloc(10*sizeof(int));//为指针分配大小为10个整数的内存空间。
二、正确的申请和释放内存
指针使用之后,如果不释放指针所使用的内存,就会造成内存的泄露,这样就会有大量内存由于没能释放,别的程序不可以使用这部分内存,如果一个程序不停申请内存而不去释放内存,很快就会造成系统的崩溃。那么如何正确的申请和释放内存呢。
1、指针初始化,上面已讲
2、正确的申请内存
如何申请内存才算是正确的申请内存呢?首先要判断指针是否为空,如果不为空,则释放该指针所指向的内存块,如果不释放这块内存,而直接就申请内存,就会造成内存的泄露。申请内存后,一定要判断是否申请成功。
如:int* pInteger=NULL;//指针定义处
...
if(pInteger != NULL)
{
free(pInteger);
pInteger=NULL;//指针释放之后并不为空,要设置其为空
}
pInteger=(int*)malloc(10*sizeof(int));
if(pInteger != NULL)
{
printf("内存申请没有成功/n!");
exit(0);
}
...
3、内存释放
程序使用完了指针,一定要记得释放指针指向的内存。释放后一定要记得设置指针为空指针。因为free函数在释放指针后,只是单纯的释放了该指针指向的内存空间,而没有将指针赋为空值。所以一定要记得在释放指针后将指针赋为空值。
如:
int* pInteger=NULL;//指针定义处
...
free(pInteger);//释放指针
pInteger=NULL; //指针赋为空值
三、使用指针时一定要判断指针是否为空
在使用指针时一定要判断指针是否为空,如果为空,则做相应的操作。如果不做判断,则可能错误的使用空指针。
如:char* dest=NULL;
...
strcpy(dest,"string");//如果dest为空则出错
 
正确的使用方法为:
if(dest == NULL)
{
dest=(char*)malloc(7*sizeof(char));//因为字符串以“/0”结束,
//所以要申请7个字符的内存
//判断内存申请是否成功
...
}
strcpy(dest,"string");
 
在指针的使用过程中,基本上要注意的问题就是这些

转载于:https://www.cnblogs.com/I-L-o-v-e-z-h-o-u/p/4950528.html

<think>首先,用户的问题基于系统提示和参考的引用内容。用户的问题是:“我想了解结构体指针的内存申请销毁方法请问如何使用C/C++申请释放结构体指针内存”。系统提示要求:-所有行内数学表达式使用$...$格式。-独立公式使用$$...$$格式。-使用中文回答。-生成相关问题。-在回答中引用的段落末尾自然地添加引用标识。用户提供了引用[1]和[2],主题是关于C/C++结构体指针的使用,特别是内存申请释放。引用[1]强调了使用结构体指针作为函数参数来提高效率,并提到使用malloc和free。引用[2]给出了一些结构体定义的代码和讨论内存申请。关键点:-内存申请:C中常用malloc,C++中可用malloc或new。-内存释放:C中用free,C++中用free(如果使用malloc)或delete(如果使用new)。-结构体指针:用户可能想知道如何为结构体指针动态分配和释放内存。回答结构:1.**结构体指针的定义和初始化**:解释如何定义结构体指针。2.**内存申请**:描述使用malloc(C)或new(C++)分配内存。3.**内存释放**:描述使用free(C)或delete(C++)释放内存。4.**注意事项**:包括指针赋值、内存泄漏、空指针检查等。5.**代码示例**:提供简单的代码例子来演示。用中文回答:-整个回答必须是中文的,因为提示说“使用中文回答”。生成相关问题:-在回答结束时,生成2-3个相关问题。引用标识:-如果有直接引用的部分,在末尾添加[^1]或[^2]。从系统提示看,这些引用是提供的,所以我应该在相关内容后自然地添加引用标识。回顾示例:-在快速排序的示例中,引用了[^1],所以我需要在回答中适当添加。回答的详细内容:1.**介绍**:简要说明结构体指针的内存申请释放。2.**申请内存**:-在C语言中,使用malloc函数,分配sizeof(struct)的大小。-在C++中,类似,但也可以使用new操作符。-提到指针初始化为NULL或直接分配。3.**释放内存**:-使用free释放由malloc分配的内存。-在C++中,如果使用new,则用delete。-强调释放后设置指针为NULL避免野指针。4.**注意事项**:-内存泄漏的风险:如果不释放,内存会泄漏。-空指针检查:在malloc后检查是否为NULL。-正确计算大小:使用sizeof(struct)。5.**代码示例**:-提供一个简单的C例子,定义一个结构体,使用malloc申请,free释放。生成相关问题:-例如:1.结构体指针在函数参数中如何高效使用?2.如何避免使用结构体指针时的内存泄漏?3.在C++中,使用new和malloc有什么区别?最终回答结构:-开头回答用户问题。-中间详细解释。-结尾添加相关问题。</think> ### 结构体指针的内存申请销毁方法 在C/C++编程中,动态地为结构体指针申请释放内存是常见操作,可以提高程序的灵活性和效率。这主要通过堆内存分配函数实现,使用时需注意内存管理的正确性以避免泄漏或野指针问题。以下我将基于您的引用内容,分步解释方法和注意事项。 #### 1. **结构体指针的定义和初始化** 在申请内存前,需先定义结构体类型和相关指针。结构体指针的初始化推荐设置为`NULL`,以表示尚未分配内存。 - **C语言示例**: ```c // 定义结构体类型 typedef struct Person { char name[50]; int age; } Person; // 声明指针并初始化为NULL Person *p = NULL; ``` - 引用[1]强调指针初始化的重要性:指针在32位系统占用4字节,在64位系统占用8字节,初始化为`NULL`能避免野指针问题[^1]。 #### 2. **申请内存的方法** 动态内存申请使用堆分配函数,核心是计算结构体大小并使用`sizeof`运算符。C中用`malloc`,C++中可用`malloc`或`new`(更推荐`new`在C++中)。 - **使用malloc (C/C++通用)**: ```c // 为指针申请内存:分配Person结构体大小的空间 p = (Person*) malloc(sizeof(Person)); if (p == NULL) { // 错误处理:确保内存分配成功,否则退出或重试 exit(EXIT_FAILURE); } // 赋值或使用 strcpy(p->name, "Alice"); p->age = 30; ``` - **使用new (C++专用)**: ```cpp Person *p = new Person(); // 调用构造函数(如果有) p->age = 30; ``` - **关键注意事项**: - 申请内存后**必须检查是否成功**(如`p == NULL`),因为内存不足时分配会失败[^1]。 - 对包含指针成员的结构体(如字符串),需单独申请成员内存(参考引用[2],字符串往往在堆上开辟空间)[^2]。 - 计算大小时使用`sizeof(struct)`而非固定值,确保兼容性[^1]。 #### 3. **释放内存的方法** 内存使用完后必须及时释放,以避免内存泄漏。释放函数需匹配申请方式:`malloc`配`free`,`new`配`delete`。 - **使用free (C/C++)**: ```c if (p != NULL) { free(p); // 释放内存 p = NULL; // 设置为NULL,防止野指针 } ``` - **使用delete (C++)**: ```cpp if (p != nullptr) { delete p; // 调用析构函数 p = nullptr; // 设置为空指针 } ``` - **关键注意事项**: - 释放后**必须将指针设为NULL**,避免后续误用野指针(如再次释放导致崩溃)[^1]。 - 对包含动态成员的指针结构体,释放需**逐层处理**:先释放成员内存,再释放结构体(示例在引用[2]中涉及字符串成员的释放)[^2]。 - 在多线程环境中,释放需确保无竞争条件。 #### 4. **整体代码示例(C语言)** 以下是一个完整的C语言例子,结合申请释放: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义结构体 typedef struct { char* name; // 字符串成员需单独申请 int age; } Person; int main() { // 声明并初始化指针 Person *p = NULL; // 申请结构体内存 p = (Person*)malloc(sizeof(Person)); if (p == NULL) { fprintf(stderr, "内存申请失败\n"); return 1; } // 申请字符串成员内存 p->name = (char*)malloc(50 * sizeof(char)); if (p->name == NULL) { free(p); // 失败时立即释放结构体 return 1; } strcpy(p->name, "Bob"); p->age = 25; // 使用结构体指针 printf("Name: %s, Age: %d\n", p->name, p->age); // 释放内存:先成员后结构体 free(p->name); // 释放字符串 p->name = NULL; free(p); // 释放结构体 p = NULL; // 设为NULL return 0; } ``` - **为什么高效**:引用[1]说明,传递结构体指针而非结构体本身(如函数参数),可减少内存复制开销[^1]。 #### 5. **最佳实践常见陷阱** - **效率优化**:如引用[1]所述,结构体作为函数参数时,优先传递指针而非值,尤其当结构体数据量大时(如文件或网络数据),以减少栈开销[^1]。 - **内存泄漏防范**: - 使用工具(如Valgrind)检查泄漏。 - 确保每次`malloc/free`或`new/delete`成对出现。 - **安全性**:在C++中,建议用智能指针(如`std::unique_ptr`)自动管理释放。 - **错误案例**: - 忘记释放内存:导致资源耗尽。 - 释放后使用指针:引发崩溃。 - 错误大小计算:如`malloc(4)`而非`sizeof(struct)`,造成溢出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值