C语言学习记录——动态内存开辟常见的错误

简介: C语言学习记录——动态内存开辟常见的错误

一、对NULL指针的解引用操作

当我们用malloc函数申请了一块很大的空间,然后没有判断是否申请成功就对指针进行解引用,就有可能产生错误(为NULL指针时)

例如:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p = (int*)malloc(1000000);//申请一块大空间
    /*if (p == NULL)     //一般情况我们会判断是否申请成功
    {
        perror("main");
        return;
    }*/
    int i = 0;
    //而此时没有判断就对指针进行解引用
    for (i = 0; i < 10; i++)
    {
        *(p + i) = i;    //导致对NULL指针进行解引用,产生错误
    }
    free(p);
    p = NULL;
    return 0;
}


二、对动态开辟空间的越界访问

在申请了一块空间且没有去调整其大小的情况下,在使用的过程中使用了超出其空间的情况,即为越界访问内存,也是常见错误之一。

例如:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p = (int*)malloc(10 * sizeof(int)); //动态开辟一块空间,相当于一个10个整型的数组
    if (p == NULL)
    {
        perror("main");
        return;
    }
 
    int i = 0;
    for (i = 0; i < 40; i++) //此处的40显然超出了10个整型,会造成越界访问
    {
        *(p + i) = i;
    }
    free(p);
    p = NULL;
    return 0;
}


三、使用free释放非动态开辟内存

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int arr[10] = { 0 };
    int* p = arr;
    free(p);  //错误!!
    return 0;
}


四、使用free释放一块动态开辟内存的一部分

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p = (int*)malloc(10 * sizeof(int));
    if (p == NULL)
    {
        perror("main");
        return;
    }
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        *p++ = i;
    }
    free(p);
    p = NULL;
 
    return 0;
}


五、多次释放同一块动态开辟的内存

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p = (int*)malloc(10 * sizeof(int));
    if (p == NULL)
    {
        perror("main");
        return;
    }
    free(p);
    //...
    //...
    //...
    free(p);   //错误
    return 0;
}

为避免出现这种错误,我们在释放完之后将指针p赋为空指针。这样即使二次使用free函数时,传入空指针也是不起任何作用的。

即,

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p = (int*)malloc(10 * sizeof(int));
    if (p == NULL)
    {
        perror("main");
        return;
    }
    free(p);
    p = NULL;
    //...
    //...
    //...
    free(p); //free函数什么都不做
    return 0;
}


六、动态开辟内存忘记释放(内存泄露)

动态开辟的空间,有两种回收方式:

  • 主动free
  • 程序结束
  • 看下面的代码段:
#include <stdio.h>
#include <stdlib.h>
void test()
{
    int* p = (int*)malloc(5 * sizeof(int));
    if (p == NULL)
    {
        perror("test");
        return;
    }
    //...
    //...
    //最后忘记释放内存
}
int main()
{
    test();
    //...
    //...
    return 0;
}

在test函数中,创建了局部变量p,也在堆区动态开辟了一块空间。最后执行完test函数忘记释放空间,而出了test函数之后,局部变量p销毁,那就再也找不到那块空间的地址,不能再进行释放空间的操作。

即发生了内存泄露。

内存泄漏 (Memory leak)是在 计算机科学 中,由于疏忽或错误造成程序未能释放已经不再使用的 内存 。. 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

目录
相关文章
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
35 3
|
7天前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
44 12
|
4天前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
68 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
28天前
|
C语言
【c语言】动态内存管理
本文介绍了C语言中的动态内存管理,包括其必要性及相关的四个函数:`malloc`、``calloc``、`realloc`和`free`。`malloc`用于申请内存,`calloc`申请并初始化内存,`realloc`调整内存大小,`free`释放内存。文章还列举了常见的动态内存管理错误,如空指针解引用、越界访问、错误释放等,并提供了示例代码帮助理解。
38 3
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
56 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
1月前
|
编译器 程序员 C语言
深入C语言:动态内存管理魔法
深入C语言:动态内存管理魔法
|
1月前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数
|
30天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
25 0
|
1月前
|
C语言
保姆级教学 - C语言 之 动态内存管理
保姆级教学 - C语言 之 动态内存管理
20 0