• C和指针 第11章 动态内存分配 11.10 问题


    /*1. 在你的系统中,能够声明的静态数组的最大长度是多少?使用动态内存,最大能够获取的内存块有多大?*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <limits.h>

    /*
    ** 静态数组的最大长度在ULONG_MAX和LLONG_MAX长度之间。每次加1看编辑器的报告就能知道最大长度。 
    ** double d[ULONG_MAX];
    */
    int main( void ){
        long mb = pow( 2, 10 ) * pow( 2, 10 );
        int counter;
        
        printf( "mb = %ld\n", mb );
        counter = 0;
        while( malloc( mb ) ){
            counter++;
        }
        printf( "the system can allocate %d MBs bytes memory.\n", counter );

        return EXIT_SUCCESS;
    }
    /* 输出: 

    */ 

    2. 如果一次请求分配500字节的内存,实际获得的动态内存数量总共有多大?如果一次请求分配5000字节,又如何?它们有区别吗?如果有,如何解释? 
    英文答案原文:
    There are two explanations possible.Requesting smaller chunks may allow more memory to be allocated because the amount of memory left over after the last allocation will be smaller.This would make the total for the smaller requests larger.More likely, though,is that the total for the smaller requests is smaller:this is due to the overheed of the extra space that malloc attache to the memory in order to keep track of the size of each allocated chunk.
    答案中文翻译:
    可能会有两种解释。申请更小的数据块会使得更多的内存得到分配,因为上一次分配剩余的内存大小会变得更小。这将使较小的请求的总数更大。更多的情况是,实际获得的内存数量更大,因为会分配额外的头部空间用于追踪每个被分配的数据块的大小。
    /* 这个我能力暂时不够,不能用代码进行证明。有没有大神帮帮忙,用代码进行验证的,感激不尽呢!*/ 
    转载于:https://www.cnblogs.com/jingliang10101/p/9809068.

    3. 在一个从文件读取字符串的程序中,有没有什么值可以合乎逻辑地作为输入缓冲区的长度?
    解析:
    如果输入包含在一个文件中,它肯定是由其他程序(例如编辑器)放在那儿的。如果是这种情况,最长行的长度是由编辑器程序支持的,它会做出一个合乎逻辑的选择,确定你的输入缓冲区的大小。 

    4. 有些C编译器提供了一个称为alloca的函数,它与malloc函数的不同之处在于它在堆栈上分配内存。这种类型的分配有什么优点和缺点?
    解析:
    主要的优点是当分配内存的函数返回时,这块内存会被自动释放。这个属性是由堆栈的工作方式决定的,它可以保证不会出现内存泄漏。但这种方法也存在缺点:由于当函数返回时被分配的内存将消失,因此它不能用于存储那些回传给调用程序的数据。 
    5. 下面的程序用于读取整数,整数的范围在1和从标准输入读取的size之间,它返回每个值出现的次数。这个程序包含了几个错误,你能找出它们吗? 
    /*
    int *frequency( int size ){
        int *array;
        int i;
    */
        /*
        ** 获得足够的内存来容纳计数。 
        */
    /*
        array = (int *)malloc( size * 2 );
    */    
        /*
        ** 调整指针,让它后退一个整型位置,这样我们就可以使用范围1-size的下标。
        */
    /*
        array -= 1;
    */    
        /*
        ** 把各个元素清零。 
        */
    /*
        for( i = 0; i <= size; i += 1 ){
            array[i] = 0;
        } 
    */    
        /*
        ** 计数每个值出现的次数,然后还回结果。 
        */
    /*
        while( scanf( *%d*, &i ) == ){
            array[i] += 1;
        } 
        free( array );
        return array;

    */
    解析:
    a. 用字面值常量2作为整型值的长度。这个值在整型值长度为2字节的机器上能正常工作。但在4字节整数的机器上,实际分配的内存将只是所需内存的一半,所以应该换用sizeof。
    b. 从malloc函数返回的值未检查。如果内存不足,它将是NULL。
    c. 把指针退到数组左边界来调整下标的范围或许行得通,但它违背了标准中关于“指针不能越过数组边界”的规定。
    d. 指针经过调整之后,第1个元素的下标变成了1,接着for循环将错误地从0开始。在许多系统中,这个错误将破坏malloc所使用的用于追踪堆的信息,常常导致程序崩溃。
    e. 数组增值前并未检查输入值是否位于合适的范围内。非法的输入可能会以一种有趣的方式导致程序崩溃。
    f. 如果数组应该被返回,它不能被free函数释放。 
    #include <stdio.h>
    #include <stdlib.h>

    int *frequency( int size );

    int main( void ){
        int *pi;
        int size;
        int i;
        
        size = 4;
        pi = frequency( size ); 
        for( i = 0; i < size; ++i ){
            printf( "the number of %d is %d\n", i + 1, pi[i] );
        }
        printf( "\n" );
        free( pi );
        
        return EXIT_SUCCESS;
    }

    /* 
    ** changed and correct frequency function。 
    */
    int *frequency( int size ){
        int *array;
        int i;
        int j;
        
        /*
        ** 获得足够的内存来容纳计数。 
        */

        array = (int *)malloc( size * sizeof(int) );
        /*
        ** 验证内存分配是否成功。 
        */
        if( !array ){
            printf( "memory allocation fails.\n" );
            return NULL;
        }
        /*
        ** 把各个元素清零。 
        */
        for( i = 0; i < size; i += 1 ){
            array[i] = 0;
        }     
        
        /*
        ** 计数每个值出现的次数,然后还回结果。 
        */
        j = 0;
        while( j++ < size && scanf( "%d", &i ) == 1 && i < size && i >= 0){
            array[i - 1] += 1;
        } 
        
        /*
        ** 返回一个指向动态分配的指针。 
        */
        return array;

    /* 输出:

    */

    6. 假定需要编写一个程序,并希望最大限度地减少堆栈的使用量。动态内存分配能不能提供帮助?使用标量数据又该怎样?
    解析:
    动态内存能够提供帮助。因为动态内存是在堆上面分配内存的,而不是在堆栈上分配内存的。标量数据不能提供帮助,标量数据一般都是在堆栈上分配空间,会占用堆栈空间。 

    7. 在程序11.4b中,删除两个free函数的调用会导致什么结果?
    解析:
    导致动态分配的内存不能够及时释放,导致其一直占用内存空间,间接延长其他程序的运行时间。 
     

  • 相关阅读:
    java计算机毕业设计酒店后厨供应商订单合并系统源码+数据库+lw文档+系统
    压缩包已知密码却跳过密码界面直接弹出解压
    聊聊DisposableBeanAdapter
    Flutter——最详细(CustomScrollView)使用教程
    数据结构day44
    云服务器上传文件到阿里云盘
    Redis基础
    【前端精进之路】JS篇:第3期 执行上下文
    基于 Vue2 组件之间的通信
    Transformer 系列 Interpret Vision Transformers as ConvNets with Dynamic Convolutions 论文阅读笔记
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/125466479