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

C程序调试模式正常运行、正常模式崩溃问题(已解决)

问题定位与修复方案

嘿,我一眼就揪出了导致你代码崩溃的核心问题——这是个非常经典的内存分配错误,刚好能解释为什么调试模式能跑但正常模式会崩溃:

在CreatePerson函数的第一行内存分配代码里:

newPerson=(Person*)malloc(sizeof(newPerson));

这里newPerson是个指针(Person*类型),所以sizeof(newPerson)得到的只是指针本身的大小(通常是4或8字节,取决于你的系统是32位还是64位),而不是Person结构体实际需要的内存空间。这就导致你只分配了一小块内存,根本装不下整个Person结构体的所有成员。

调试模式下,编译器会给内存分配额外的“保护填充”和检测机制,所以即使你越界访问内存,也不会立刻触发崩溃;但发布模式下没有这些保护,当你尝试给numOfKids、kids这些结构体成员赋值时,就会写到不属于你的内存区域,直接触发崩溃。

具体修复步骤

1. 修正结构体内存分配

把上面的错误代码改成:

newPerson = malloc(sizeof(Person));

(顺便提一句:在C语言里完全不需要强制转换malloc的返回值,强制转换反而可能隐藏一些潜在的类型问题,比如忘记包含stdlib.h导致的隐式声明错误)

2. 修复内存泄漏问题

你的代码在分配失败时直接返回NULL,但没有释放已经分配的内存(比如newPerson->name或者已经分配好的部分kids数组元素),这会导致内存泄漏。比如如果分配某个kids[i]失败,之前分配的newPerson、newPerson->name以及前面的kids[0]到kids[i-1]都会变成无法释放的内存垃圾。

可以在每个错误分支里手动清理已分配的资源,比如:

  • 当newPerson->kids分配失败时:
    if (newPerson->kids==NULL){
        free(newPerson->name);
        free(newPerson);
        return NULL;
    }
    
  • 当某个kids[i]分配失败时:
    if (newPerson->kids[i]==NULL){
        // 先释放已经分配的所有kids元素
        for (int j=0; j<i; j++){
            free(newPerson->kids[j]);
        }
        free(newPerson->kids);
        free(newPerson->name);
        free(newPerson);
        return NULL;
    }
    

3. 其他潜在优化点

  • scanf("%s", tempName)存在缓冲区溢出风险,建议改成scanf("%255s", tempName)(假设MAX_NAME是256),限制输入长度,避免超出tempName的数组大小。
  • 确保InitPersonValues函数正确初始化结构体的所有成员(比如把kids指针初始化为NULL),避免出现野指针。

修正后的完整代码示例

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

#define MAX_NAME 256

typedef struct {
    char* name;
    int id;
    int numOfKids;
    char** kids;
} Person;

void InitPersonValues(Person* p) {
    p->name = NULL;
    p->id = 0;
    p->numOfKids = 0;
    p->kids = NULL;
}

Person* CreatePerson(){
    Person* newPerson = malloc(sizeof(Person));
    if (newPerson == NULL){
        return NULL;
    }
    InitPersonValues(newPerson);

    char tempName[MAX_NAME];
    int id;
    int kidsNumber;

    printf("Name:\n");
    // 限制输入长度,防止缓冲区溢出
    scanf("%255s", tempName);
    newPerson->name = malloc(1 + strlen(tempName));
    if (newPerson->name == NULL){
        free(newPerson);
        return NULL;
    }
    strcpy(newPerson->name, tempName);

    printf("ID:\n");
    scanf("%d", &id);
    newPerson->id = id;

    printf("Num of kids:\n");
    scanf("%d", &kidsNumber);
    newPerson->numOfKids = kidsNumber;

    if (kidsNumber > 0){
        newPerson->kids = malloc(kidsNumber * sizeof(char*));
        if (newPerson->kids == NULL){
            free(newPerson->name);
            free(newPerson);
            return NULL;
        }
        for (int i=0; i<kidsNumber; i++){
            printf("Kid #%d name:\n", i+1);
            scanf("%255s", tempName);
            newPerson->kids[i] = malloc(strlen(tempName) + 1);
            if (newPerson->kids[i] == NULL){
                // 清理已分配的资源
                for (int j=0; j<i; j++){
                    free(newPerson->kids[j]);
                }
                free(newPerson->kids);
                free(newPerson->name);
                free(newPerson);
                return NULL;
            }
            strcpy(newPerson->kids[i], tempName);
            printf("%s\n", newPerson->kids[i]);
        }
    }
    return newPerson;
}

内容的提问来源于stack exchange,提问作者A. Lev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:30:28