欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C和指针第十一章 动态内存分配

程序员文章站 2024-02-29 18:18:22
...

11.2malloc和free

malloc函数从内存池中提取一块合适的内存(没有初始化),并向程序返回一个指向该内存起始位置的指针,

free函数将它归还内存池

函数原型如下:

void * malloc( size_t size );//这个要求是字节数,而且必须要对这个指针检查是否为NULL,因为内存池不一定有那么多内存

void free( void  * pointer );//参数为NULL(没有效果的),或者之前申请的内存指针


11.3calloc和realloc

函数原型:

void *calloc( size_t num_elements, size_t element_size );//和malloc的请求内存数量方式不同,calloc包括所需元素的数量和每个元素的字节数,而且这块内存已经初始化为0

void realloc( void *ptr, size_t new_size );//realloc用于修改一个已经分配的内存块大小,如果是扩大的话,新内存就会放在原来内存块的后面,新内存没有进行任何初始化,如果是缩小,原先的内存块的尾部内存将会杯拿掉,剩余部分原先内存依然保留,如果无法改变大小,realloc将分配另外一块正确大小的内存,内容也会复制过去所以使用malloc后,就不能在使用指向旧内存的指针,而是使用返回指针   。如果第一个参数是NULL。就和malloc一样


11.4使用动态分配的内存

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *pi;
    pi = malloc( 25 * sizeof( int ) );
    if( pi == NULL )
    {
        printf("out of memory!\n");
        exit(1);
    }
    int *pi2,i;
    pi2 = pi;
    for( i = 0; i < 25; i++ )
    {
        *pi2++ = i;
    }
    printf("使用下标来显示\n");
        for( i = 0; i < 25; i++)
    {
        printf("%d\n", pi[i]);
    }


    return 0;
}

11.5常见的动态内存错误

对NULL指针进行解引用,对分配的内存进行操作时越过边界,释放非动态分配内存,试图释放一块动态分配内存的一部分,以及一块动态内存被释放后被继续使用

这里书上讲了如何定义实现使用一个错误检查分配器,我觉得重点就在于是否对malloc函数的结果进行NULL检查,然后观察是否需要初始化


不能使用free释放内存的一部分

这里应该是使用realloc函数


还有一个重点就是不要使用已经释放的内存

就是你对一个指向动态分配内存的指针进行了复制,而且这个拷贝有好几份,所以需要保证程序中使用这块内存的地方在这块内存被释放之前停用


还有内存分配后不用了就要释放啊,不然内存会越来越少,最终需要重启系统哦


11.6内存分配实例

#include <stdio.h>
#include <stdlib.h>
//读取排序和打印一列整型值这里是升序
//这里是对qsort函数的一些理解http://www.cnblogs.com/sooner/archive/2012/04/18/2455011.html
int compare_integers( void const *a, void const *b )
{
    int const *pa = a;
    int const *pb = b;
    return *pa > *pb ? 1 : *pa < *pb ? -1 : 0;//升序的话就是a>b,返回一个正值小就负值,相等为0
}

int main()
{
    int *array;
    int n_values;
    int i;
    printf( "一共要有几个值?\n" );
    if ( scanf( "%d", &n_values) != 1 || n_values <= 0  )
    {
        printf("输入值有误\n");
        exit(1);
    }
    //分配内存,
    array = malloc( n_values * sizeof( int ));
    if( array == NULL )
    {
        printf(" 没有那么多内存了\n");
        exit(1);
    }
    //读取数值
    for( i = 0; i < n_values; i++)
    {
        printf(" 输入数值\n");
        if( scanf ( "%d", array + i ) != 1)
        {
            printf("出错");
            free( array );
            exit(1);

        }
    }
    //排序了
    qsort( array, n_values, sizeof( int ),compare_integers );
    for( i = 0; i < n_values; i++)
    {
        printf( " 排序后的结果 %d\n", array[i] );

    }
    free(array);
    return 0;
}



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//使用动态分配内存制作一个字符串的一份拷贝
char *strup( char const *string );
int main()
{
    char *a = "hhhhhhhhh";
    char *b;
    b = strup(a);
    puts( b );
    //printf("Hello world!\n");
    return 0;
}
char *strup( char const *string )
{
    char *new_string;
    new_string = malloc( strlen( string ) +  1 );
    if( new_string !=NULL )
        strcpy( new_string, string );
    return new_string;
}

这个是书上那一堆关于变体的代码,我倒是觉得不复杂,就很累啊,然后,最后释放哪里我就没有打上去

#include <stdio.h>
#include <stdlib.h>

int main()
{
    //存货记录的声明
    typedef struct
    {
        int cost;
        int supplier;
    } Partinfo;
    //存储装配件专用信息的结构
    typedef struct
    {
        int n_parts;
        struct SUBASSYPART
        {
            char partno[ 10 ];
            short quan;
        } *part;
    }Subassyinfo;
    //存货记录结构,她是一个变体记录
    typedef struct
    {
        char partno[10];
        int quan;
        enum { PART, SUBASSY } type;
        union
        {
            Partinfo *part;
            Subassyinfo *subassy;
        } info;
    }Invrec;
    //用于创建装配件存货记录的函数
    Invrec *create_subassy_record (int n_parts)
    {
        //为Inverc部分分配内存
        Invrec * new_rec;
        new_rec = malloc( sizeof( Invrec ));
        if( new_rec != NULL )
        {
            //内存分配成功现在存储
            new_rec->info.subassy = malloc( sizeof( Subassyinfo ));
            if( new_rec->info.subassy != NULL )
            {
                //为零件获取一个足够大的数组
                new_rec->info.subassy->part = malloc( n_parts * sizeof ( struct SUBASSYPART ) );
                if( new_rec->info.subassy->part != NULL )
                {
                    new_rec->type = SUBASSY;
                    new_rec->info.subassy->n_parts = n_parts;
                    return new_rec;
                }
                //内存已经用完,释放原先分配的内存
                free( new_rec->info.subassy );
            }
            free( new_rec );
        }
        return NULL;
    }

        //printf("Hello world!\n");
    return 0;
}