首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在free()之后将指针设置为NULL总是一个好习惯吗?

当然,这是一个很好的实践,在 free() 函数之后将指针设置为 NULL 可以帮助释放内存并防止内存泄漏。这对于任何使用指针的 C 语言程序来说都是一个很好的实践,无论是否在 free() 函数之后,因为这样可以确保内存被正确管理。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C语言进阶-动态内存管理柔性数组

如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体使用的时候使用者自己来决定(需要用强制类型转化成所需要的指针类型...* ptr); 注意: 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的 如果参数 ptr 是NULL指针,则函数什么事都不做 注:malloc 和 free 都声明 stdlib.h...(单位字节) 返回值调整之后的内存起始位置(同样需要更具需要进行强制类型转化来访问空间) realloc调大内存空间时存在两种情况: 情况1:原有空间之后有足够大的空间 要扩展内存就直接原有内存之后直接追加空间...原来空间的数据不发生变化 realloc()返回原指针 情况2:原有空间之后没有足够大的空间 堆空间上找到另一个空间(合适大小的连续空间,足够所要开辟空间的大小)来开辟 同时原来开辟空间所存有的内存进行拷贝...,并且不能重复释放同一空间,如果及时置空,再次free也只是free空地址,对空地址free不会有任何操作 即使有两个指向同一内存的,也只能free一个,因为释放完之后,原有的内存空间已经释放掉了,再进行释放就是重复释放

64020

常见的C编程段错误及对策

检查了他的代码之后,没有发现什么问题,于是单步调试。观察这个结构体变量的内存时,发现有几个成员的值乱码。就是其中某一个乱码惹得祸!...(a)); memset 函数有三个参数,第一个是要被设置的内存起始地址;第二个参数是要被设置的值;第三个参数是要被设置的内存大小,单位byte。...5、内存释放之后 既然使用free 函数之后指针变量p 本身保存的地址并没有改变,那我们就需要重新把p的值变为NULL: p = NULL; 这个NULL 就是我们前面所说的“栓野狗的链子”。...比如:free(p)之后,你用if(NULL != p)这样的校验语句还能起作用?...所以一定要记住一条:free之后,一定要给指针NULL。 同时留一个问题:对NULL 指针连续free 多次会出错?为什么?如果让你来设计free函数,你会怎么处理这个问题?

1.5K41
  • 常见内存错误

    初始化堆栈中的数据 对申请的内存或自动变量进行初始化是一个好习惯,例如: int test() { int *a = (int*) malloc(10); /*判断是否申请成功*/...指针运算以指向对象大小单位 对于下面的代码,ptr1 + 1之后,到底移动了多少个字节?ptr2 + 1呢?...不可再引用 在这个例子中可能很容易发现问题,但是大型程序中,这样的问题可能很难发现,一个建议就是释放a的内存后,显式地a置NULL。...即: free(a); a = NULL; 避免对NULL解引用 对于上面的例子,a置NULL之后还不够,我们需要经常对入参进行检查,避免对NULL解引用。这样就避免引用已经释放的内存。...上面所列出的仅仅是一些比较常见的内存相关问题,总结如下: 自动变量或申请的内存需要初始化 避免缓冲区溢出 指针不等同于指向的对象 指针运算以指向大小单位 避免对NULL或已释放的内存进行引用 申请的内存不使用时及时释放

    82520

    栈和队列的习题详解(2):用队列实现栈

    掉然后设置指针,这样我们便可以写完这个题目,肯定很多读者朋友和我一样,知道了思路但是代码不太会打,下面小编讲述这些功能的代码实现!...,前面也说过,这里我们就涉及到了倒数据这一个操作,首先我们需要先找到不为空的队列和空的队列,此时我们也不知道是哪一个队列是空的,所以小编给出的操作就是我们先默认设置两个队列结构体指针,第一个队列是不空队列指针...,第二个队列是空队列指针之后我们通过if语句来判断第一个队列是否空,如果空我们把让不为空队列是第二个,空一个,这里我们就完成了寻找不为空队列的操作,之后我们就要通过循环,来开始让不为空队列的数据转移到空队列中...刚开始,我们先通过取栈顶的操作设置一个新的变量来存储队头数据,之后我们把队头的数据放入到空的队列中,之后我们进行出队列操作,此时空队列已经有1这个数据了,如下图所示: 之后我们继续重复进行上面的操作...掉,对于栈中的队列,我们可以采取用他们各自的销毁操作来实现,销毁完以后,不要忘记我们的obj也是动态开辟出来的,此时我们需要free掉obj,然后让它指向空就好,养成好习惯,尽量不要写出野指针,此时销毁操作也是完成了

    4210

    【初阶数据结构篇】双向链表的实现(赋源码)

    * plist = NULL; //LTInit(&plist);//初始化,只有一个哨兵位,空链表 //保持接口一致性使用一级指针 LTNode* plist = LTInit2()...,我们让它的next指针和prev指针都指向自己(否则只有一个头结点时就不叫循环链表了) 我们可以和单链表一样,plist的地址传过去,然后进行初始化 void LTInit(LTNode** pphead...) { //创建头结点(哨兵位) *pphead = LTBuyNode(-1); } 为了保持接口的一致性(之后的方法我们都是传一级指针),此处也采用一级指针更好 LTNode* LTInit2...NULL; } main函数中调用完这个函数后,别忘了把plist置空!!!...总之,可以发现虽然双向链表比单链表多了一个前驱指针,但在实现方法上比单链表简单很多 链表与顺序表的比较 最后,介绍完链表与顺序表后,二者进行总结比较 以上就是双向链表的实现方法啦,各位大佬有什么问题欢迎评论区指正

    11710

    【C进阶】——动态内存管理详解 及 经典笔试题解析

    使用后: 我们初始化之后,里面放的就是0到9了。 如果参数size_t size0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但返回的指针不应被解引用。...所以我们尽量不要这样试,况且这样做也没什么意义,申请一个大小0的空间? 那申请的空间使用完之后,我们是不是什么都不用管了呢?...为了避免这种情况发生: 我们释放掉p指向的空间之后,要及时p置空。...因为如果free的参数 ptr 接收的是NULL指针,不执行任何操作。 所以: 使用free释放一块动态内存空间后,及时指向起始位置的指针置空是一个好习惯。...我们一起来分析一下: 首先str还是一个char*的指针,给它赋值NULL,然后调用GetMemory(), GetMemory()内部创建了一个字符数组p,放了一个字符串"hello world

    15610

    【C语言】动态内存管理(下)(realloc函数)

    那么本文中,我继续给大家介绍另一个非常重要且实用的动态内存管理的函数——realloc函数,以及再深入探讨一下free函数的使用细节,避免使用动态内存函数时,由于不及时释放或者时胡乱释放所造成不必要的麻烦出现...大家不妨回想一下,无论是malloc或者是calloc申请的动态内存空间一旦申请了之后就无法再调整空间的大小(除非自己设置一小段代码,进行调整)。...2.2 针对情况2(realloc后面没有足够的内存空间) 当是情况2的时候,原有空间之后没有足够多的空间时,拓展的方法是:堆空间上寻找另一个合适大小的连续空间来使用。...因为,如果realloc函数申请申请空间失败之后,会返回一个NULL值,也就说不仅realloc申请失败了就连之前申请的那块空间也找不到了。这就会造成严重的信息丢失的问题。...3.1 对NULL指针的解引用操作 void test() { int* p = (int*)malloc(INT_MAX / 4); *p = 20;//如果p的值NULL,就会出现问题 free

    4210

    【数据结构】——双向链表详细理解和实现

    循环和不循环 这实现单链表的时候,我们链表的最后一个节点next指针置位了空指针NULL),而循环的链表中,我们会将最后一个节点的next指针指向链表的头结点,对于双向链表,头节点的prev...prev指针指向头节点,next指针指向头节点的下一个节点;然后修改头节点的next指针和头节点下一个节点的prev指针即可。...->next = phead->next->next; free(del); del = NULL; } 2.7、双向链表尾删数据 尾插是删除链表的尾节点,释放内存之后,让尾节点的上一个节点...; } 2.9、指定节点pos之前插入数据 根据我们查找到的节点,在其之前插入数据,首先创建新节点,新节点的prev指针指向pos的前一个节点,新节点的next指针指向pos;再修改...2.10、指定节点pos之后插入数据 根据查找到的节点,在其之后插入数据;首先创建节点,新节点的prev指针指向pos,新节点的next指针指向pos的下一个节点;然后修改pos的next

    2110

    【初阶数据结构篇】单链表的实现(附源码)

    ,并将其置空,表示此时链表空,之后需要的时候我们通过插入一个节点并始终保持plist指向单链表第一个节点即可。...(p1); p1 = NULL; } *pphead = NULL; } - 这里我们要改变plist的值了,所以传二级指针(其实也可以传一级,只不过调用完后别忘了把plist置空哦(❁´◡...,一定要先改newnode的next指针,否则找不到pos下一个节点了 单链表指定位置之后插入数据 void SLTInsertAfter( SLTDataType x, SLTNode* pos)...,尾节点释放并把前一个节点next指针空 当链表只有一个节点时,不需要将前一个节点next指针空,此时需要将plist置空 单链表指定位置删除数据 void SLTErase(SLTNode...尾插/尾删中,都需要依据链表是否空/链表是否多于一个节点来分情况讨论,目的是避免对空指针进行解引用造成的错误。

    12810

    【初阶数据结构】——带头双向循环链表(C描述)

    一个头结点就完事了吗?首先哨兵位的头结点不存储有效数据,它的数据域我们可以随便给个值。 那指针域呢? 我们新创建的结点指针域默认赋值NULL,是指向空的。那头结点的指针域我们需要改动?...因为我们初始化之后,有一个哨兵位的头结点在这里,我们需要有一个指针来指向这个头结点,以便我们来访问链表。...另外: 这里我们释放完哨兵头之后虽然phead = NULL;,把头指针置空了,但其实并不会影响外面真正的头指针,还是形参与实参的关系。...所以其实函数内部这句phead = NULL;加不加都无所谓,因为函数调用结束这个指针变量也就销毁了,当然加上是一个好习惯。...但是需要我们函数外部手动真正的头指针置一下空,不置的话就是一个指针了。 5.

    10510

    动态内存管理学不懂,小代老师带你深入理解动态内存管理(上卷)

    • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏是未定义的。 • 如果参数 ptr 是NULL指针,则函数什么事都不做。...函数原型如下: void* realloc(void *ptr,size_t size) • ptr 是要调整的内存地址 • size 调整之后新⼤⼩ • 返回值调整之后的内存起始位置。...• realloc调整内存空间的是存在两种情况: ◦ 情况1:原有空间之后有⾜够⼤的空间 ◦ 情况2:原有空间之后没有⾜够⼤的空间 情况1 当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间...free(ptr); ptr=NULL return 0; } 如果realloc申请成功我们把地址赋值给ptr没有什么问题,如果申请失败呢,realloc会返回一个NULL指针,申请失败就算了...= NULL) { ptr = p; } //释放 free(p); p = NULL; return 0; } 我们把realloc的返回值返回个我们设置指针,然后判断不为NULL再赋值给

    3710

    【数据结构初阶】复杂链表复制+带头双向循环链表+缓存级知识

    找到这样的关系之后,我们copy链表中的所有指针指向都画出来,然后再去思考下一步怎么做。...细节2: 当我们尾插时,其实需要那么一个current指针来随着我们的链表长度增加,使其始终指向我们链表的尾结点,所以实现抽离新链表时使用尾插,不要忘记newtail向后移动,否则你会一直newtail...; newnode->prev = NULL; return newnode; } 由于我们头插,尾插,pos之前位置插入等接口里面总是要进行结点空间的开辟,所以我们这一功能单独抽离出来,让其形成一个接口...值得注意的是,释放空间之后指针空是一个好习惯,也是一种好的代码风格,我们应该提倡,这样做可以防止他人误用掉我们释放空间后的地址,调试时更容易观察出问题。...因为我们的free不会讲指针自动置空的,所以我们要手动置NULL

    27810

    【初阶数据结构】一文讲清楚 “堆” 和 “堆排序” -- 树和二叉树(二)(内含TOP-K问题)

    我还会针对堆排序给大家再次拓展一个大家以后编程的道路上,会经常的遇到的一个实际问题:就是一大堆数据中找出最大或最小的前几个数,这个问题的本质就是堆排序,我们也这种问题,称为"TOP-K"问题。...堆的实现 讲完堆的基本概念之后,我就要详细的给大家讲讲堆是怎样用代码实现的,内容很丰富,希望大家能够好好看! 2.1 堆的结构体设置 我们之前讲过了,堆是一棵完全二叉树,我们可以用顺序表来实现。...void HeapDestory(Heap* php) { assert(php); free(php->arr); php->arr = NULL;//养成好习惯 php->size...开始讲之前,我会结合以下的这棵完全二叉树进行讲解(这里我拿大堆举例) 可以看到它物理结构时候的样子,那我们先插入一个数字看看改变之后的样子。...; free(a); a = NULL; } 大家为了方便测试,可以data.txt这个文本文件中,将其中10个值改为都大于1000的,这样的话,测试的结果就显而易见了。

    3610

    malloc函数java_malloc函数详解及用法举例

    void* 表示未确定类型的指针。c,c++规定,void* 类型可以强制转换为任何其它类型的指针。...malloc动态内存分配函数头文件#include #include malloc函数使用要求 这个函数要实现的功能是系统中分配一段连续的可用的内存,具体有如下要求: 1.malloc分配的内存大小至少...size参数所指定的字节数. 2.malloc的返回值是一个指针,指向一段可用内存的起始地址. 3.多次调用malloc所分配的地址不能有重叠部分,除非某次malloc所分配的地址被释放掉. 4.malloc.../n”); free(p); return 0; } malloc函数用法实例2 #include #include int main() { // Code… char *Ptr = NULL;...Ptr = (char *)malloc(100 * sizeof(char)); if (NULL == Ptr) { exit (1); } gets(Ptr); // code… free(Ptr

    1.3K10

    C++之指针使用

    GetMemory(str, 100); // str 仍然 NULL  strcpy(str, "hello"); // 运行错误 } 编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是...任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。   (2)指针p被free或者delete之后,没有置NULL,让人误以为p是个合法的指针。   ...五 内存耗尽怎么办   如果在申请动态内存时找不到足够大的内存块,malloc和new返回NULL指针,宣告内存申请失败。通常有三种方式处理“内存耗尽”问题。   ...(1)判断指针是否NULL,如果是则马上用return语句终止本函数。   (2)判断指针是否NULL,如果是则马上用exit(1)终止整个程序的运行。   ...(3)用_set_new_hander函数new设置用户自己定义的异常处理函数。

    64710

    【数据结构初阶】单链表的实现

    ->next = NULL; } /*SLTNode* tail = *pphead; SLTNode* prev = NULL;*///前驱指针,让我们的tail总是prev的前面,让prev...*///只有一个结点的时候,我们的prev是NULL,对NULL进行访问那就是非法访问 //这样的代码会导致经典的野指针问题出现 //我们tail所在空间释放掉之后,相当于前一个结点中的next所指向的空间被释放掉...其实这个问题不易被发现,但也挺容易发现的,就是我们这里依然用了值传递,我们头结点的地址做了一份临时拷贝,如果此时链表空,我们newnode的地址赋值给了这个拷贝值,可是这有用?...我们这一种特殊情况拿出来,单独进行处理,如果是一个结点的话,我们释放掉其空间之后这块儿空间地址进行置NULL,这样我们的链表就变为空链表了。...(*pphead); *pphead = next; } } 销毁接口: 我们free某个结点之前先将这个结点后面的结点的地址用一个指针变量存放起来,然后再进行freefree之后,我们进行迭代

    33720

    栈和队列的习题详解 (4):设计循环队列

    ,但是此时这个队列的首和尾是结合起来的,并且这个题目要求我们的队列的长度是一定的,所以我们队列满了以后是不可以继续插入数据的,对于普通的队列我们之后就不能在插入数据了,但是循环队列不一样,我们可以移除一个数据以后...,此时可以看作把一个动态的空间静态化了,我们插入数据的时候,此时我们使用链表的时候会显示的繁琐一点,因为我们填完队列以后,之后删除数据后还得插入数据,此时链表的操作就显的比较繁琐一点,所以小编推荐此时我们设置这个队列的底层逻辑是数组...当我们书写队列的结构体内容的时候,也是比较有讲究的,小编设置的这个队列肯定有队头元素和队尾元素,此外还需要有一个待动态开辟的指针,并且还需要有一个变量,我们看看上面的初始化函数,此时这个函数是规定让我们开辟指定空间大小的队列...,我们就需要去销毁这个队列了,一提到销毁操作,我们正常的操作就是把那些我们动态开辟过的资源给free掉,此时我们首先要把结构体里的arr给free掉,然后让它指向空,养成不写野指针的良好习惯之后再把结构体另外三个变量变为...= obj -> pour = 0; free(obj); obj = NULL; } 以上便是循环队列的题目实现,这个题目的难点就在于我们如何处理循环这一个功能,此时多设置出一块空间便是这个题目的点睛之笔

    4010

    【C语言进阶篇】常用动态内存分配 malloc calloc realloc free

    如果开辟成功,则返回一个指向开辟好空间的指针。 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。...函数返回失败怎么办 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。...如果开辟失败,就会给 p 返回NULL指针。 而我们一旦对空指针进行访问不会,越界访问越界了嘛?...这时就需要使用free来释放,我们申请的动态内存空间 编程的好习惯是,每次使用完malloc都要使用free释放空间 下面我们就来介绍一下free函数 2️⃣ 动态内存函数 free   ⛳️C语言提供了另外一个函数...这里我们思考一个问题,realloc也会返回失败那么就会返回NULL指针

    38210

    【链表】算法题(一) ----- 力扣 牛客

    一、移除链表元素 移除链表中值val的元素,并返回新的头节点 思路: 题目上这样说,我们就可以创建一个新的链表,值不为val的节点,尾插到新的链表当中,最后返回新链表的头节点。...指针指向l2;再l1指向l2,l2指向l3(l2下一个节点);直到遍历结束,结束条件(l2等于NULL)此时l1指向的就是反转后的链表的头节点。...定义两个快慢指针,fast和slow刚开始都指向链表的头节点,fast每次向前走两个节点,而slow指针每次向前走一个节点;最后当fast指针或者fast的next指针NULL遍历结束...注:这里使用动态内存来给newhead开辟空间,记得将其释放掉,养成好习惯。...思路: 创建两个链表,一个链表l1,存放值小于val的节点;另一个链表l2,存放值大于等于val的节点。最后两个链表连接起来,返回l1链表的头节点即可。

    2010
    领券