常见的动态内存错误

简介: 常见的动态内存错误

常见的动态内存错误有很多,笔者仅仅举出几个典型的列子,供大家参考一下!!


1.对NULL(空指针)进行解引用操作!!


请看代码:


#include <stdio.h>
#include <stdlib.h>
int main()
{
  int* p = (int*)malloc(20);
  *p = 5;
  return 0;
}

显而易见的,这段代码是错误的!!没有对malloc函数,开辟内存空间失败后的判断!!


malloc函数开辟了20个字节的空间,将p指向这20个字节,p指向这20个字节的起始位置,而p作为整型指针,对其解引用,访问4个字节!将5赋值给*p,则第一个元素为5!但是,代码看着虽好,但是却显得不少很严谨!!原因在于:malloc函数的返回值不确定是否为:NULL(空指针),当malloc开辟空间失败,会返回NULL(空指针),而对空指针解引用,会出现错误!!


下面请看正确的书写代码格式:


#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
  int* p = (int*)malloc(20);
  if (*p == NULL)
  {
  //如果p为NULL(空指针)将进行怎样的操作??
  perror("malloc");
  return 1;
  }
  else
  {
  *p = 5;
  }
  free(p);
  p = NULL;
  return 0;
}

在上述的正确代码中,具体内容的变化,我们可以通过调试可以看出来!!在此,笔者就先不做过多的解析!!


2.对动态内存开辟的越界访问!


请看笔者的代码:


#include <stdio.h>
#include <stdlib.h>
int main()
{
  int* p = (int*)malloc(20);
  if (p == NULL)
  {
  return 1;
  }
  //使用
  int i = 0;
  for (i = 0; i < 20; i++)
  {
  *(p + i) = i;
  }
  //打印
  for (i = 0; i < 5; i++)
  {
  printf("%d ", *(p + i));
  }
  //释放
  free(p);
  p = NULL;
  return 0;
}


在上述的代码中:malloc函数开辟了20个字节,用来存放5个整型,但是,在for循环里面,进行了越界访问!所以,导致程序崩溃!!


0a2653c851af460fa595bd959398a8f1.png2d65d23f6d4748949b924e4057485923.png


3.对非动态开辟的内存,使用free释放!


int main()
{
  int num = 10;
  int* p = &num;
  //……代码的其他内容!
  //释放
  free(p);
  p = NULL;
}

在上述代码中:int num = 10;  是一个局部变量,进入这个程序的时候开始创建,出这个程序的时候,就进行销毁,不需要进行free释放!


在该段代码的最后:用free来释放,会导致程序的崩溃!!


6de278e6d6694ce5bb08e7e842b7e74b.png


4.使用free释放一块动态开辟内存的一部分!


请看笔者的代码:


#include <stdio.h>
#include <stdlib.h>
int main()
{
  int* p = (int*)malloc(40);
  if (p == NULL)
  {
  return 1;
  }
  int i = 0;
  for (i = 0; i < 5; i++)
  {
  *p = i;
  p++;
  }
  //释放
  free(p);
  p = NULL;
}


上述代码,也会导致程序崩溃!!


首先,开辟了40个字节,Int 类型,可以存放10给整型数据,但是,在for循环中,由于 for (i = 0; i < 5; i++);使用了5个!!,随着p++的进行,此时,p已经指向第五个元素的位置,不再是指向起始位置了!!


12c3b7f3f8814309a195c64f051d4445.png


但是,在free(p)的释放中,也释放不了后面的空间,导致程序崩溃!!!


在free释放的时候,p指向的不再是,动态内存开辟的起始位置了!!因此需要用另外一个指针来遍历!!


总结:对于动态内存开辟的空间,一定要记录其起始位置,若没有记录起始位置,一直进行++(往后走),最终会导致这片空间无法释放!!


5.动态开辟内存忘记释放(内存泄漏)!


请看笔者的代码:


#include <stdio.h>
#include <stdlib.h>
int* get_memory()
{
  int* p = (int*)malloc(40);
  //其他使用代码!!
  return p;  //返回动态内存空间的起始地址!!
}
int main()
{
  int* ptr = get_memory();
  //使用
  //…………其他代码
  //忘记释放了!!
  return 0;
}

在函数体的部分:    return p的作用: 是返回动态内存空间的起始地址!!


但是在最后没有进行free所以,出现了错误!!


正确的free代码为:


free(ptr);

ptr = NULL;

在这里,释放的是:ptr所指向的空间!!


忘记释放不再使用的动态开辟的空间,会造成内存泄漏!!切记,动态开辟的空间,一定要释放,并且正确释放!!


相关文章
动态内存管理之realloc函数
动态内存管理之realloc函数
|
2月前
|
C++ 容器
常见的内存分配错误
【10月更文挑战第11天】
35 2
|
7月前
|
编译器
常见的动态内存错误总结(二)
本文总结了两种常见的动态内存错误:内存泄漏和野指针。在示例代码中,内存泄漏发生于动态分配内存后未进行释放,导致程序结束时内存无法回收。野指针问题出现在函数返回栈上创建的变量地址,由于栈空间销毁,指针变成无效,访问时会导致错误。文章强调了使用`static`修饰局部变量可以延长其生命周期以避免野指针,以及释放内存后应将指针置`NULL`以防止后续误用。
42 3
|
7月前
|
存储 安全 编译器
常见的动态内存错误总结(一)
该文讨论了C语言中与动态内存和指针相关的常见问题。首先,强调了对NULL指针解引用的危险性,示例展示了未检查动态内存分配结果导致的问题,并指出`free()`函数传入NULL是安全的。接着,通过代码解释了指针传值调用时的陷阱,说明了为何直接调用`GetMemory(str)`无法改变`Test`函数中`str`的值。文章还提到了动态内存的越界访问和非法释放,包括释放非动态内存、只释放内存的一部分以及重复释放同一块内存的错误情况。最后,建议在释放内存后将指针设为NULL以防止后续误用。
61 1
|
7月前
6个常见的动态内存的错误和动态内存经典笔试题
6个常见的动态内存的错误和动态内存经典笔试题
|
C语言
【动态内存管理】动态内存函数
【动态内存管理】动态内存函数
|
编译器
C进阶:动态内存函数 malloc calloc realloc free及常见动态内存开辟错误(下)
C进阶:动态内存函数 malloc calloc realloc free及常见动态内存开辟错误(下)
68 1
|
存储 程序员 编译器
C语言 — 动态内存管理(动态内存函数)
本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C++程序的内存开辟区域
99 0
|
编译器
动态内存函数和常见的动态内存错误
动态内存函数和常见的动态内存错误