You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言字符串内存分配异常咨询:仅分配1字节却可存完整字符串?

C语言动态分配字符串的越界问题分析

你不想预定义固定大小的char数组(比如char[999]),于是尝试给struct Node里的char* name只分配1字节内存,结果出现了奇怪的现象:用scanf输入字符串后,printf能输出完整内容,但调试时控制台只显示第一个字符,同时你怀疑存在内存泄漏,不确定超出首字符的内容存在哪里。

先贴出你的代码:

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

struct Node {
    int val;
    char *name;
    struct Node *next;
};

int main()
{
    struct Node *list;
    list = (struct Node *)malloc(sizeof(struct Node));
    list->name = (char *)malloc(sizeof(char));
    printf("Enter a string");
    scanf("%s", list->name);
    printf("%s", list->name);
    return 0;
}

核心问题:内存越界访问

你只给name分配了1字节内存,但scanf写入的字符串(除首字符外)会直接写到这块内存之外的区域——这属于未定义行为,C标准不保证这种情况的结果,完全取决于当前内存布局。

为什么现象矛盾?

  • printf能输出完整内容:因为你写入的越界内存暂时还没被其他程序或数据覆盖,printf会顺着指针一直读取直到遇到字符串结束符'\0',所以能读到完整输入。
  • 调试器只显示首字符:调试器只会展示你实际分配的1字节内存里的内容,越界部分不属于这块分配的内存,所以不会显示。

关于内存泄漏的误解

这里不存在内存泄漏,内存泄漏是指分配的内存不再使用却未释放。你遇到的是内存越界写入,这种行为会破坏其他内存区域的数据,后续可能导致程序崩溃、数据错乱,甚至被利用为安全漏洞,比泄漏危险得多。

正确的可变长度字符串处理方式

方法1:临时缓冲区+按需分配

先把输入读到一个临时固定大小的缓冲区,再根据实际字符串长度分配内存并复制:

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

struct Node {
    int val;
    char *name;
    struct Node *next;
};

int main()
{
    struct Node *list = malloc(sizeof(struct Node));
    if (list == NULL) {
        perror("malloc for Node failed");
        return 1;
    }

    char temp_buf[256]; // 选一个足够容纳预期输入的临时缓冲区
    printf("Enter a string: ");
    scanf("%s", temp_buf);

    // 分配内存:字符串长度+1(存储结束符'\0')
    list->name = malloc(strlen(temp_buf) + 1);
    if (list->name == NULL) {
        perror("malloc for name failed");
        free(list);
        return 1;
    }
    strcpy(list->name, temp_buf);

    printf("%s\n", list->name);

    // 用完记得释放内存,避免泄漏
    free(list->name);
    free(list);
    return 0;
}

方法2:使用scanf的%ms格式符(GCC等编译器支持)

%ms会自动根据输入长度分配足够的内存,无需手动计算:

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

struct Node {
    int val;
    char *name;
    struct Node *next;
};

int main()
{
    struct Node *list = malloc(sizeof(struct Node));
    if (list == NULL) {
        perror("malloc for Node failed");
        return 1;
    }

    printf("Enter a string: ");
    // %ms会自动分配内存,将指针存入list->name
    if (scanf("%ms", &list->name) != 1) {
        perror("scanf failed");
        free(list);
        return 1;
    }

    printf("%s\n", list->name);

    // 释放自动分配的内存和Node内存
    free(list->name);
    free(list);
    return 0;
}

注意事项

  • 永远要检查malloc的返回值,避免空指针访问导致程序崩溃
  • 动态分配的内存必须在使用完后释放,否则会真的出现内存泄漏
  • 内存越界是C语言中极其危险的行为,一定要严格避免

内容的提问来源于stack exchange,提问作者dogano25

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 14:19:02