栈区,堆区,动态内存开辟,错误及原因

简介: 栈区,堆区,动态内存开辟,错误及原因
#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
#include<stdlib.h>
//动态内存开辟的常见错误
//1.对NULL的解引用操作
//int main()
//{
//    int* p = (int*)  malloc(10000000000000000);
//    int i = 0;//没有对NULL==0的判断
//    for (i = 0; i <= 10; i++)
//    {
//         *(p + i)=i;
//    }
//    return 0;
//}
2.对动态开辟空间的越界访问
//int main()
//{
//    int i = 0;
//    int* p = (int*)malloc(10 * sizeof(int));
//    if (p == NULL)
//    {
//        return 1;
//    }
//    for (i = 0; i <= 40; i++)//越界
//    {
//        *(p + i) = i;
//    }
//    free(p);
//    p = NULL;
//    return 0;
//}
//3.使用free()释放非动态开辟的空间(只能是堆区)
//int main()
//{
//    int arr[10]={0};//栈区
//    int* p = arr;
//    free(p);
//    p = NULL;
//    return 0;
//}
//4.使用free()只释放非动态开辟的空间的一部分
//int main()
//{
//    int i = 0;
//    int* p = (int*)malloc(10 * sizeof(int));
//    if (p = NULL);
//    return 1;
//    for (i = 0; i <= 5; i++)
//    {
//        *p++ = i;
//    }
//    free(p);//此时的p已经不是p指向的原来的位置,因为p此时已经无法通过p找到最初的空间,
//    //且如果此时通过p释放空间,此时的p=NULL,则变为释放*(p+4)的空间,错误
//    p = NULL;
//    return 0;
//}
//5.对同一块内存开辟的空间多次释放
//int main()
//{
//    int* p =(int*) malloc(100);
//
//    free(p);
//
//    free(p);//多次释放--会出错,但是如果free(p);p=NULL;free(P);p=NULL,则无事发生
//    p = NULL;
//
//    return 0;
//}
//6.动态内存开辟忘记释放---在程序是24小时运行时,程序不会结束,内存一直泄露,浪费内存空间
//void test()
//{
//    int* p = (int*)malloc(10000);
//    if (p = NULL)
//    {
//        return 1;
//    }
//    //使用----使用之后已经无法返回,空间忘记释放
//}
//int main()
//{
//    test();
//    return 0;
//}
//动态开辟的空间两种回收方式:
// 1.主动使用free()
// 2.程序(不是函数)结束
//在堆上开辟和在栈上开辟的变量不一样,在堆上开辟不销毁,在栈上开辟销毁
//1.在堆上开辟时,地址有意义错误如下,改正如下
#include<string.h>
//void GetMemory(char* p)
//{
//    p = (char*)malloc(100);
//
//}
//void test(void)
//{
//    char* str = NULL;
//    GetMemory(str);
//    strcpy(str, "hello word");
//    printf(str);
//}
//
//int main()
//{
//    test();
//    return 0;
//}
//错误理由:
//str传给GetMemory函数的时候是值传递,所以Getmenory函数的形参p是str的一份临时拷贝,在Getmenory函数内部
//动态申请空间的地址,存放在p中,不会影响外边str,所以当Getmenory函数返回之后,str依然是NULL,所以strcpy
//会失败
//当Getmenory函数返回后,形参p销毁,使得动态开辟的100个字节存在内存泄露,无法释放
//应改为(传址法)
//char* GetMemory(char* p)
//{
//    p = (char*)malloc(100);    //----malloc是在堆上开辟的
//    return p;
//
//}
//void test(void)
//{
//    char* str = NULL;
//    str=GetMemory(str);//传址
//    strcpy(str, "hello word");
//    printf(str);//
//    printf("hello word");//与str打印结果一样,因为传的是h的地址,h的地址所指的字符串
//    free(str);
//    str = NULL;
//
//}
//int main()
//{
//    test();
//    return 0;
//}
//也可改为:(二级指针法)
//void GetMemory(char** p)
//{
//    *p = (char*)malloc(100);//----malloc是在堆上开辟的
//
//}
//void test(void)
//{
//    char* str = NULL;
//    GetMemory(str);
//    strcpy(str, "hello word");
//    printf(str);
//    free(str);
//    str = NULL;
//}
//int main()
//{
//    test();
//    return 0;
//}
//2.在栈上开辟时,(如数组等局部变量)地址没意义
//char* GetMemory(void)
//{
//    char p[]="hello word";    //----malloc是在栈上开辟的,出了函数,p数组空间就还给操作系统,
//    //返回地址是没有实际意义的,如果通过地址访问内存,就是非法内存
//    return p;
//
//}
//void test(void)
//{
//    char* str = NULL;
//    str=GetMemory();
//    printf(str);
//
//}
//int main()
//{
//    test();
//    return 0;
//}
int* f1(void)
{
    int x = 10;//在栈区内创建的局部变量x出了函数就销毁,取地址无意义
    return(&x);
    int* ptr;//局部变量不初始化就是随机值,是野指针
    *ptr = 10;
    return ptr;
}
//全局变量,静态变量,static修饰局部变量,放数据段---静态区----代码段----常量字符串,可执行代码,指针代码
//局部变量,局部数组等放栈上
//malloc,calloc,realloc放在堆上


相关文章
|
19天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
46 5
|
1月前
|
存储
栈内存
栈内存归属于单个线程,也就是每创建一个线程都会分配一块栈内存,而栈中存储的东西只有本线程可见,属于线程私有。 栈的生命周期与线程一致,一旦线程结束,栈内存也就被回收。 栈中存放的内容主要包括:8大基本类型 + 对象的引用 + 实例的方法
24 1
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
77 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
4月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
4月前
|
存储 程序员 编译器
堆和栈内存的区别是什么
【8月更文挑战第23天】堆和栈内存的区别是什么
336 4
|
5月前
|
存储 Rust JavaScript
Rust 问题之TypeScript 代码,变量 s 存储在栈内存中还是堆内存中如何解决
Rust 问题之TypeScript 代码,变量 s 存储在栈内存中还是堆内存中如何解决
|
5月前
|
存储 设计模式 监控
Java面试题:简述JVM的内存结构,包括堆、栈、方法区等。栈内存优化的方法有 哪些?
Java面试题:简述JVM的内存结构,包括堆、栈、方法区等。栈内存优化的方法有 哪些?
51 0
|
5月前
|
Java 开发者
Java面试题:Java内存管理精要与多线程协同策略,Java内存管理:堆内存、栈内存、方法区、垃圾收集机制等,多线程编程的掌握,包括线程创建、同步机制的原理
Java面试题:Java内存管理精要与多线程协同策略,Java内存管理:堆内存、栈内存、方法区、垃圾收集机制等,多线程编程的掌握,包括线程创建、同步机制的原理
41 0
|
5月前
|
算法 Java 开发者
Java面试题:Java内存探秘与多线程并发实战,Java内存模型及分区:理解Java堆、栈、方法区等内存区域的作用,垃圾收集机制:掌握常见的垃圾收集算法及其优缺点
Java面试题:Java内存探秘与多线程并发实战,Java内存模型及分区:理解Java堆、栈、方法区等内存区域的作用,垃圾收集机制:掌握常见的垃圾收集算法及其优缺点
42 0
|
5月前
|
存储 算法 Java
Java面试题:解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用,Java中的多线程是如何实现的,Java垃圾回收机制的基本原理,并讨论常见的垃圾回收算法
Java面试题:解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用,Java中的多线程是如何实现的,Java垃圾回收机制的基本原理,并讨论常见的垃圾回收算法
78 0