【C语言指针进阶讲解】第五章:指针与内存管理

第五章:指针与内存管理

5.1 动态内存分配

在C语言中,动态内存分配允许程序在运行时申请所需的内存空间,而不是在编译时决定。这对处理可变大小的数据结构如链表、树和动态数组特别有用。C语言提供了几个标准库函数来实现动态内存分配,它们分别是:malloccallocreallocfree

复习malloc, calloc, realloc, free
  1. malloc

    • 用于分配指定大小的内存块,返回指向内存块开头的指针。
    • 返回的内存块未被初始化。
    int *p = (int*)malloc(10 * sizeof(int)); // 分配10个整型数据的内存空间
    if (p == NULL) {
        // 处理内存分配失败
    }
    
  2. calloc

    • 用于分配指定数量相同大小的内存块,并初始化为0。
    • 参数为元素数量和每个元素的大小。
    int *p = (int*)calloc(10, sizeof(int)); // 分配并初始化10个整型数据的内存空间
    if (p == NULL) {
        // 处理内存分配失败
    }
    
  3. realloc

    • 用于调整先前分配的内存块的大小。
    • 若重新分配成功,返回新的地址;若失败,返回NULL且原来的内存块保持不变。
    p = (int*)realloc(p, 20 * sizeof(int)); // 调整内存块大小以容纳20个整型数据
    if (p == NULL) {
        // 处理内存重新分配失败
    }
    
  4. free

    • 用于释放先前分配的内存,使其能够被重新利用。
    free(p); // 释放先前分配的内存
    p = NULL; // 避免悬空指针
    
示例代码:动态分配和释放内存中的指针数组

下面的代码展示了如何动态分配和释放一个指针数组:

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

int main() {
    int **array;
    int rows = 4, cols = 5;

    // 动态分配指针数组
    array = (int**)malloc(rows * sizeof(int*));
    if (array == NULL) {
        perror("Failed to allocate memory");
        return -1;
    }

    // 为每个指针分配数组
    for (int i = 0; i < rows; i++) {
        array[i] = (int*)malloc(cols * sizeof(int));
        if (array[i] == NULL) {
            perror("Failed to allocate memory");
            return -1;
        }
    }

    // 初始化并打印数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            array[i][j] = i * cols + j;
            printf("%d ", array[i][j]);
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < rows; i++) {
        free(array[i]);
    }
    free(array);

    return 0;
}

以上代码动态分配了一个4x5的二维数组,并在程序结束前正确释放所有分配的内存。

5.2 内存泄漏与调试工具
内存泄漏的概念与常见原因

内存泄漏是指程序未能正确释放先前分配的内存空间,导致这些内存空间在程序运行期间一直无法重新利用,最终可能导致内存耗尽。以下是一些常见原因:

  1. 忘记释放内存:如忘记调用free
  2. 指针丢失:如指针被重新赋值而未先free原来的内存。
  3. 局部指针失效:如在函数内分配的内存未被返回。
使用工具如valgrind检测内存泄漏

Valgrind是一个强大的内存调试工具,它可以检测内存泄漏、多重释放(double free)和非法访问等问题。使用方法如下:

  1. 安装valgrind(根据操作系统不同,安装命令可能不同)。

    对于Debian/Ubuntu系统:

    sudo apt-get install valgrind
    
  2. 通过valgrind执行程序:

    valgrind --leak-check=full ./your_program
    

    示例输出:

    ==12345== HEAP SUMMARY:
    ==12345==     in use at exit: 72 bytes in 3 blocks
    ==12345==   total heap usage: 9 allocs, 6 frees, 7,256 bytes allocated
    ==12345== 
    ==12345== 72 bytes in 3 blocks are definitely lost in loss record 2 of 2
    ==12345==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
    ==12345==    by 0x400556: main (main.c:7)
    ==12345== 
    ==12345== LEAK SUMMARY:
    ==12345==    definitely lost: 72 bytes in 3 blocks
    ==12345==    indirectly lost: 0 bytes in 0 blocks
    ==12345==      possibly lost: 0 bytes in 0 blocks
    ==12345==    still reachable: 0 bytes in 0 blocks
    ==12345==         suppressed: 0 bytes in 0 blocks
    ==12345== 
    ==12345== For counts of detected and suppressed errors, rerun with: -v
    ==12345== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    

    以上示例输出显示了72字节的内存泄漏,以及哪个代码位置导致了这一泄漏。通过这样的输出,程序员可以快速定位并修复内存泄漏问题。

通过本章的学习,读者应该能够理解并掌握如何在C语言中正确进行动态内存分配和释放,如何识别和修复内存泄漏问题,这对于编写高效、可靠的C程序非常重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值