首页 > 编程笔记 > C语言笔记 阅读:673

malloc在c语言中的用法(非常详细)

malloc() 是 C语言中的一个内存分配函数,用于在内存上分配指定大小的连续内存空间。

malloc() 函数是 C语言中动态内存管理的核心函数之一,使用 malloc() 函数分配的内存在函数返回后不会被自动释放,因此需要在适当的时候手动释放内存,以防止内存泄漏。

函数 malloc 的原型如下:
void* malloc(size_t size);
参数 size 表示要分配的内存大小,以字节为单位。通常使用 sizeof 操作符确定数据类型的大小。

如果内存分配成功,那么 malloc() 函数将返回一个指向新分配内存的指针(void* 类型)。如果内存分配失败(例如,请求的内存大小超过可用内存),那么 malloc() 函数将返回 NULL。

我们一旦通过 malloc() 函数成功地申请了内存空间,就可以根据需要将返回的指针转为任意类型的指针。只要通过指针访问内存,就不能超过这段内存空间的大小。

下面是一个使用 malloc() 函数的示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int *pInt = NULL;
    pInt = malloc(sizeof(int));
    double *pDouble = NULL;
    pDouble = malloc(sizeof(double));
    *pInt = 123;
    *pDouble = 3.1415926;
    printf("%d %f", *pInt, *pDouble);
    return 0;
}
运行结果为:

123 3.141593

malloc(sizeof(int)) 申请了 4 字节的内存空间,若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。我们可以把这 4 字节的内存空间用于存储 int 类型的数据,只需通过赋值将 void* 转换为 int*,然后对 int* 类型的指针进行取值,接着将该值赋值给该指针。

同样,malloc(sizeof(double)) 申请了 8 字节的内存空间,若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。我们可以把这 8 字节的内存空间用于存储 double 类型的数据,只需通过赋值将 void* 转换为 double*,然后对 double* 类型的指针进行取值,接着将该值赋值给该指针。

在 C语言中,void * 可以通过赋值转换为其他类型的指针:
int *pInt = NULL;
pInt = malloc(sizeof(int));
double *pDouble = NULL;
pDouble = malloc(sizeof(double));

另外,一定要严格保证使用指针访问成功申请的内存空间时,不要超过申请时预定的空间大小,例如:
double *pDouble = NULL;
pDouble = malloc(sizeof(int));
*pDouble = 3.1415926;
上面的代码申请了 sizeof(int),即 4 字节大小的空间。若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。接着,我们把它转换为 double* 类型的指针,并赋值给 pDouble。

但是,若对 pDouble 指针使用取值运算符 *,将访问从首地址开始的 8 字节的内存空间,超出了申请时预定的 4 字节空间,这种做法可能导致程序崩溃。

若需要动态地创建一个有 10 个 int 元素的数组,那么需要申请 sizeof(int) * 10 字节的内存空间,或者也可以写成 sizeof(int[10])。
int *pArr = NULL;
//  申请sizeof(int) * n,转换为int *使用
pArr = malloc(sizeof(int) * 10);
//  给数组元素赋值
for (int i = 0; i < 10; i++)
   pArr[i] = i;
//  输出数组元素
for (int i = 0; i < 10; i++)
   printf("%d ", pArr[i]);
之前讨论的都是 malloc() 函数成功申请到内存的情况,作为一个稳健的程序应当也考虑失败的情况。若 malloc() 函数申请内存空间失败,它将返回 NULL。为 NULL 指针取值将导致程序崩溃。建议每次通过 malloc() 函数申请内存空间时都对返回值进行判断:
int *pInt = NULL;
pInt = malloc(sizeof(int));
//  判断malloc函数是否成功申请了内存空间
if (pInt != NULL)
{
    //  若不为NULL,则再次使用这个指针
    *pInt = 123;
    printf("%d", *pInt);
}

C语言释放内存空间

在使用 malloc() 函数申请内存空间并完成使用后,务必记得使用 free() 函数对这段内存空间进行释放。

free() 是 C语言中用于释放之前通过 malloc() 函数分配的内存空间的内存释放函数。free() 函数也是 C语言中动态内存管理的核心函数之一。当不再需要使用动态分配的内存时,调用 free() 函数将内存归还给操作系统,以避免内存泄漏。

函数 free() 的原型如下:
void free (void* ptr);
参数 ptr 表示指向要释放的内存块的指针。这个指针应该是之前由 malloc() 函数返回的指针。如果传递给 free() 函数的指针不是这个函数返回的指针,或者已经被释放过,将导致未定义行为。

注意事项:
以下是一个使用 malloc() 函数和 free() 函数的简单示例:
int *pInt = NULL;
pInt = malloc(sizeof(int));
if (pInt != NULL)
{
    *pInt = 123;
    printf("%d", *pInt);
    //  释放内存空间
    free(pInt);
}
上述代码申请了 sizeof(int) 字节内存空间,用作 int 类型。内存使用完毕后,我们利用 free() 函数对内存空间进行释放。free() 函数的参数是 void* 类型的指针,而 void* 类型的指针可以接收任何类型的指针。因此,我们可以直接将 pInt 传递给 free() 函数,无须进行类型转换。

如果仅调用 malloc() 函数申请内存空间,而未调用 free() 函数释放内存空间,则成功申请的内存空间将保留直至程序结束。这期间程序所占用的内存空间会逐渐增大,直至无可分配空间,无法再成功申请内存空间。

下面展示了一个未释放内存的示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
   while (1)
   {
       void* p = malloc(1024 * 1024);
       printf("%d\n", p);
   }
   return 0;
}
这种情况通常是由于申请了内存空间,但忘记释放内存空间导致的。应及时释放不再使用的内存空间。

上面程序中,申请的内存空间首地址存储在指针 p 中,下一次新申请的内存空间首地址会覆盖上一次的首地址。由于没有保存内存空间的首地址,因此程序将无法再通过任何方式使用或释放这些内存空间,这种现象被称为内存泄漏。具有内存泄漏问题的代码若长时间运行,会导致程序所占用的内存空间逐渐增大,直至没有可分配的内存空间,并无法再成功申请内存空间。

相关文章