C++ / a working model

118 / 163   ·   C11   ·   约 8 分钟

插曲:内存API

先记住这句话

C程序依赖栈上的自动分配和堆上的显式请求来管理数据寿命。理解malloc与free的正确配对以及常见误用,是写出健壮软件的关键。

本篇内容
  1. 程序内存的两种类型
  2. 正确调用malloc
  3. 释放内存和典型陷阱
  4. 运行示例
  5. 动手练习

官方章节 PDF

程序内存的两种类型

函数内部声明的变量由编译器在调用栈上自动预留空间,函数返回时这些空间立刻失效。需要跨越函数调用继续存在的数据必须放到堆上,程序员负责提出请求并在用完后归还。

正确调用malloc

向malloc传入所需字节数,通常用sizeof作用于类型来计算。返回的void指针再转换成目标类型。务必检查是否为NULL。复制字符串时额外加一字节存放结束符。

释放内存和典型陷阱

每次成功的malloc最终必须用同一指针调用free。完全忘记分配、少申请一字节或重复释放都会导致崩溃或安全问题。许多新语言用垃圾回收隐藏这些细节。

常见误区

  • 把未初始化的指针交给strcpy当目标
  • 只申请strlen字节随后连结束符一起写入
  • 用完堆块却从不调用free

运行一个例子

最低标准 C11 · 完整程序 · 下载 .c

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

int main(void) {
    int stack_val = 42;
    printf("Allocated on stack: %d\n", stack_val);
    int *heap_val = (int *)malloc(sizeof(int));
    if (heap_val == NULL) {
        printf("Heap allocation failed\n");
        return 1;
    }
    *heap_val = 99;
    printf("Allocated on heap: %d\n", *heap_val);
    const char *original = "OSTEP";
    char *copy = (char *)malloc(strlen(original) + 1);
    if (copy == NULL) {
        free(heap_val);
        printf("String allocation failed\n");
        return 1;
    }
    strcpy(copy, original);
    printf("String copy: %s\n", copy);
    free(copy);
    free(heap_val);
    printf("All heap memory released\n");
    return 0;
}

在本地编译

gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-14-memory-api.c -o example && ./example

预期结果

Allocated on stack: 42
Allocated on heap: 99
String copy: OSTEP
All heap memory released

CHECK YOUR UNDERSTANDING

合上答案,试着解释。

为什么对动态分配得到的指针做sizeof只会得到指针本身的宽度?

查看参考答案

sizeof是编译期操作符,它只看见变量的静态类型,看不见运行时真正申请了多少字节。

继续查证

标准草案与官方章节会更新;版本标记只说明示例最低要求。

回到目录