• 静态内存


    变量都会申请内存,申请内存有两种方式,一种是静态内存,另外一种是动态内存。这里主要学习静态内存,静态内存的分配是由编译器实现

    静态内存的好处:

    程序员不需要考虑变量内存的申请和释放,因此不需要考虑是否有内存泄露。当程序域执行,会自动申请内存,当程序域执行完毕,会自动回收内存。

    静态内存的坏处:

    1.对于数组变量,有可能实际数据会大于数组长度,因此会导致数组越界;若将数组长度定义过大,实际使用很少,会导致内存的浪费。

    2.对于局部函数要将结果返回给主函数,对于静态内存无法实现。

    因此对于静态内存的使用,需要考虑实际场景。

    针对:对于局部函数要将结果返回给主函数,对于静态内存无法实现。有如下例子:

    例子1:

    #include<stdio.h>
    #include<string.h>
    char*  upcase(char *oldString);
    int  main(void)
    {
        char* str1;
        str1 = upcase("justTest");
        printf("%s 
    ",str1);
        return 0;
    }
    
    
    char*  upcase(char *oldString){
        int counter;
        char *newString;
        strcpy(newString,oldString);
        for(counter=0;counter < strlen(newString);counter++){
            if(newString[counter]>=97 && newString[counter] <=122){
                newString[counter] -=32;
            }
        }
        return newString;
    }

    执行结果:

    len@DESKTOP-BDP8J2M /cygdrive/e/c_study
    $ gcc staic_memory.c -o staic

    len@DESKTOP-BDP8J2M /cygdrive/e/c_study
    $ ./staic.exe
    Segmentation fault (核心已转储)

    编译没有任何警告,但是执行时直接提示段错误。

     例子2:

    #include<stdio.h>
    #include<string.h>
    
    char*  upcase(char *oldString);
    
    int  main(void)
    {
        char* str1;
        str1 = upcase("justTest");
        printf("%s 
    ",str1);
        return 0;
    }
    
    
    char*  upcase(char *oldString){
        int counter;
        char newString[100];
        strcpy(newString,oldString);
        for(counter=0;counter < strlen(newString);counter++){
            if(newString[counter]>=97 && newString[counter] <=122){
                newString[counter] -=32;
            }
        }
        return newString;
    }

    运行结果:

    $ gcc staic_memory.c -o staic
    staic_memory.c: 在函数‘upcase’中:
    staic_memory.c:25:2: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
    return newString;
    ^

    len@DESKTOP-BDP8J2M /cygdrive/e/c_study
    $ ./staic.exe
    JUSTTEST`▒_

    例子1和例子2的差别是局部函数upcase定义newString时,例子1用的char*,例子2是char[]

    结果是例子1段错误,例子2虽然有提示返回的是局部变量的地址,但是局部函数的值依然可以返回给主函数。

    从上面例子可以看到两点:

    1.strcpy函数对于局部char*的拷贝存在问题(加打印发现段错误是在执行strcpy函数的时候出现)

    2.strcpy函数对于source为char*,dest为char[],虽然会有警告,但是依然可以将地址给到主函数,可能有如下原因:

    局部函数返回local-addr,静态内存没有释放,存在泄露

    例子3:

    #include<stdio.h>
    #include<string.h>
    
    void  upcase(char *oldString,char *newString);
    
    int  main(void)
    {
        char str1[100];
        upcase("justTest",str1);
        printf("%s 
    ",str1);
        return 0;
    }
    
    void  upcase(char *oldString,char *newString){
        int counter;
        strcpy(newString,oldString);
        for(counter=0;counter < strlen(newString);counter++){
            if(newString[counter]>=97 && newString[counter] <=122){
                newString[counter] -=32;
            }
        }
    }

    运行结果:

    len@DESKTOP-BDP8J2M /cygdrive/e/c_study
    $ gcc staic_memory.c -o staic

    len@DESKTOP-BDP8J2M /cygdrive/e/c_study
    $ ./staic.exe
    JUSTTEST

    若将main函数中char[]修改为char*传递给upcase函数,依然会有段错误,在strcpy时产生段错误。

    总结:

    1.对于char*指针变量实例化必须是char[],否则若传入char*,会导致传入空地址或source和dest内存可能重叠,无法进行strcpy

    PS:对于strcpy的学习计划后面新加随笔

    2.对于局部函数或静态内存,在程序域自动申请和释放,否则会引起内存泄露。

  • 相关阅读:
    SQL Server中的事务与锁
    delphi中 dataset容易出错的地方
    Ehlib(Delphi控件) v9.2.024 D7-XE10.2 免费绿色特别版
    Delphi (Library Path Browsing Path)
    XML序列化和反序列化
    C#基础--Attribute(标签) 和 reflect(反射) 应用
    C#特性类的使用
    NOPI使用手册
    【WCF】错误处理(四):一刀切——IErrorHandler
    浅析C#中的事件
  • 原文地址:https://www.cnblogs.com/jason207489550/p/6662428.html
Copyright © 2020-2023  润新知