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

如何处理C语言含未知长度字符串的struct?程序报错求助

C语言带动态字符串结构体的问题排查与修复

核心错误点:

  • 返回栈内存地址导致野指针:create_object函数中的my_object是栈上的局部变量,函数执行完毕返回后,栈帧会被销毁,返回的指针变成无效的野指针。后续对该指针的所有读写操作都是非法内存访问,这是数值异常、程序崩溃的根本原因。
  • strncpy参数使用错误:set_word和set_another_word中,strncpy的第三个参数用了sizeof((*my_object)->a_word) + 1,但(*my_object)->a_word是指针类型,sizeof得到的是指针的字节数(32位系统为4,64位为8),并非你分配的内存长度。正确的做法是使用strlen(a_word) + 1,确保完整复制字符串及终止符。
  • 未释放结构体本身的内存:clear_memory仅释放了字符串指针指向的内存,但结构体本身如果是动态分配的,最后也需要释放,否则会造成内存泄漏。

修正后的代码:

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

typedef struct Object {
    unsigned short a_number;
    char *a_word;
    char *another_word;
} Object;

// 动态分配结构体内存并初始化成员
Object *create_object() {
    Object* p_my_object = malloc(sizeof(Object));
    if (p_my_object == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    // 初始化指针为NULL,避免后续free时操作野指针
    p_my_object->a_word = NULL;
    p_my_object->another_word = NULL;
    p_my_object->a_number = 0;
    return p_my_object;
}

void set_word(Object *my_object, const char *a_word) {
    // 先释放原有内存,防止重复调用时内存泄漏
    if (my_object->a_word != NULL) {
        free(my_object->a_word);
    }
    size_t str_len = strlen(a_word) + 1;
    my_object->a_word = malloc(str_len);
    if (my_object->a_word == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    // 已分配足够空间,用strcpy更直接
    strcpy(my_object->a_word, a_word);
}

void set_another_word(Object *my_object, const char *another_word) {
    if (my_object->another_word != NULL) {
        free(my_object->another_word);
    }
    size_t str_len = strlen(another_word) + 1;
    my_object->another_word = malloc(str_len);
    if (my_object->another_word == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    strcpy(my_object->another_word, another_word);
}

void set_number(Object *my_object, unsigned short a_number) {
    my_object->a_number = a_number;
}

void clear_memory(Object **my_object){
    if (*my_object == NULL) {
        return;
    }
    // 释放字符串内存
    free((*my_object)->a_word);
    free((*my_object)->another_word);
    // 释放结构体本身
    free(*my_object);
    // 将指针置为NULL,避免悬空指针
    *my_object = NULL;
}

int main()
{
    unsigned short a_number = 100;
    const char *a_word = "apple";
    const char *another_word = "banana";
    Object *my_object;
    
    my_object = create_object();
    set_word(my_object, a_word);
    set_another_word(my_object, another_word);
    set_number(my_object, a_number);
    
    printf("a_number: %hu\n", my_object->a_number);
    printf("a_word: %s\n", my_object->a_word);
    printf("another_word: %s\n", my_object->another_word);
    
    clear_memory(&my_object);

    return 0;
}

修正说明:

  1. create_object改为动态分配结构体内存,同时初始化所有成员,避免野指针问题。
  2. 简化了set_*函数的参数(无需双重指针,因为不需要修改结构体指针本身),修复了字符串复制的参数错误,增加了内存分配失败的错误处理,同时添加了重复调用时释放原有内存的逻辑,防止内存泄漏。
  3. clear_memory补充了结构体本身的内存释放,并将指针置为NULL,避免后续误操作悬空指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:15:36