C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍

本文主要是介绍C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、常见的动态内存错误
    • 1. 对NULL指针的解引用操作
    • 2. 对动态开辟空间的越界访问
    • 3. 对非动态开辟内存使用free()
    • 4. 使用free释放一块动态开辟内存的一部分
    • 5. 对同一块动态内存多次释放
    • 6. 动态开辟内存忘记释放(内存泄漏)
  • 二、几个经典笔试题
    • 1.
    • 2.
    • 3.
    • 4.
  • 三、 c/c++内存开辟空间图
  • 总结


前言

C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍


一、常见的动态内存错误

1. 对NULL指针的解引用操作

#include <stdio.h>
#include <stdlib.h>
int main()
{int* p = (int*)malloc(40);// 没有对malloc开辟失败的拦截,所以p有可能为空指针// 程序可能崩溃*p = 20;return 0;
}

2. 对动态开辟空间的越界访问

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{int* p = (int*)malloc(40);if (NULL == p){printf("%s\n", strerror(errno));}int i = 0;for (i = 0; i <= 10; i++) // 动态内存越界访问,程序报错{*(p + i) = i;}free(p);p = NULL;return 0;
}

3. 对非动态开辟内存使用free()

#include <stdio.h>
#include <stdlib.h>
int main()
{int a = 0;int* p = &a;free(p);p = NULL;return 0;
}

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{int* p =(int*)malloc(40);if (NULL == p){printf("%s\n", strerror(errno));}int i = 0;for (i = 0; i < 5; i++){*p = i;p++; // p 的地址一直在改变,free(p)没有指向动态内存的起始地址// 程序崩溃}free(p);p = NULL;return 0;
}

5. 对同一块动态内存多次释放

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{int* p = (int*)malloc(40);// ....free(p); // 释放了一次,但是p没有置为空指针// 此时p为野指针// p = NULL;// .....free(p); // 此时程序报错,p是野指针return 0;
}

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>void test()
{int* p = (int*)malloc(40);if (NULL == p){printf("%s\n", strerror(errno));return;}int flag = 0;scanf("%d", &flag);if (flag == 5){return;}free(p);p = NULL;
}int main()
{test();return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int* test()
{int* p = (int*)malloc(40);if (NULL == p){return p;}return p;}int main()
{// test 函数开辟空间int* ret = test();// 忘记释放return 0;
}
所以,动态开辟的空间一定要释放,并且要正确释放。

二、几个经典笔试题

1.

char* str = "hello world";
printf(“%s\n”, str); // hello world
printf(“hello world”\n); // hello world
printf(str) // hello world
str 存放 h 的地址, 所以 printf(""hello world); 和 printf(str);是一样的效果

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char* p)
{p = (char*)malloc(100);// 出了GetMemory函数 p会被销毁// 无法再找到 动态内存,所以内存泄漏
}void Test(void)
{char* str = NULL;GetMemory(str);// str 是空指针,解引用时,程序崩溃strcpy(str, "hello world");printf(str);
}int main()
{Test();return 0;
}
  1. 修改1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char** p)
{*p = (char*)malloc(100);// *p 指向str,str被赋值为动态内存的地址
}void Test(void)
{char* str = NULL;GetMemory(&str);strcpy(str, "hello world"); // hello worldprintf(str);free(str);str = NULL;
}int main()
{Test();return 0;
}
  1. 修改2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* GetMemory()
{char* p = (char*)malloc(100);// *p 指向str,str被赋值为动态内存的地址return p;
}void Test(void)
{char* str = NULL;str = GetMemory();strcpy(str, "hello world"); // hello worldprintf(str);free(str);str = NULL;
}int main()
{Test();return 0;
}

2.

#include <stdio.h>
#include <string.h>
char* GetMemory(void)
{char p[] = "hello world";return p; // 出了 函数 ,p[] 就会被销毁// 所以str 接收到了地址,但是p[]的内容被销毁, 无法被找到
}
void Test(void)
{char* str = NULL;str = GetMemory(); // str 是一个野指针printf(str); // 烫烫烫烫烫烫烫烫x魪?
}int main()
{Test();return 0;
}

3.


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100); strcpy(str, "hello");printf(str);  // hello// 但是没有释放内存空间// 可以如下释放/*free(str);str = NULL;*/
}int main()
{Test();return 0;
}

4.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>void Test(void)
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str); // 释放空间,str变成野指针if (str != NULL){strcpy(str, "world");printf(str);}
}int main()
{Test();return 0;
}

三、 c/c++内存开辟空间图

在这里插入图片描述


总结

C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍

这篇关于C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/968716

相关文章

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin

JAVA SE包装类和泛型详细介绍及说明方法

《JAVASE包装类和泛型详细介绍及说明方法》:本文主要介绍JAVASE包装类和泛型的相关资料,包括基本数据类型与包装类的对应关系,以及装箱和拆箱的概念,并重点讲解了自动装箱和自动拆箱的机制,文... 目录1. 包装类1.1 基本数据类型和对应的包装类1.2 装箱和拆箱1.3 自动装箱和自动拆箱2. 泛型2

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

C++ Primer 标准库vector示例详解

《C++Primer标准库vector示例详解》该文章主要介绍了C++标准库中的vector类型,包括其定义、初始化、成员函数以及常见操作,文章详细解释了如何使用vector来存储和操作对象集合,... 目录3.3标准库Vector定义和初始化vector对象通列表初始化vector对象创建指定数量的元素值

前端bug调试的方法技巧及常见错误

《前端bug调试的方法技巧及常见错误》:本文主要介绍编程中常见的报错和Bug,以及调试的重要性,调试的基本流程是通过缩小范围来定位问题,并给出了推测法、删除代码法、console调试和debugg... 目录调试基本流程调试方法排查bug的两大技巧如何看控制台报错前端常见错误取值调用报错资源引入错误解析错误

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C