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

CLion中C程序Debug模式正常,正常执行返回错误码0xC0000005求助

Advent of Code 2022 Day3 运行异常排查(错误码0xC0000005)

问题描述

我在用C语言完成Advent of Code 2022年第3题的挑战,代码在CLion的Debug模式下运行完全正常,但切换到正常执行(Release模式)时返回错误码-1073741819(0xC0000005)。查阅资料得知该错误码可能与栈溢出相关,但无法自行定位问题点,同时怀疑是否存在内存未释放的情况。

主程序代码

//
// Created by gusta on 2022-12-06.
//
#include "aocio.h"
#include <string.h>

int cexists(char* cp, char c, int length);
char getDuplicate(char* line);

int main() {

    FILE* fptr = openFile("../Inputs/day3.txt");

    char* line;
    while (readLine(fptr, &line)) {
        char c = getDuplicate(line);
        putchar(c);
    }

    return 0;
}

char getDuplicate(char* line) {  // Returnerar STRING_END om ingen fanns

    unsigned int length = strlen(line);

    char letters[length/2];
    char* cp = &letters[0];

    for (int i = 0; i < length/2; i++) {
        letters[i] = ' ';
    }

    for (int index = 0; line[index] != STRING_END; index++) {

        if (index < length/2) {

            int i_char = cexists(letters, line[index], length/2);
            if (i_char == -1) {
                *cp = line[index];
                cp++;
            }
        }
        else {
            if (cexists(letters, line[index], length/2) != -1) {
                return line[index];
            }
        }
    }

}

int cexists(char* cp, char c, int length) {

    for (int i = 0; i < length; i++) {
        if (cp[i] == c) {
            return i;
        }
    }
    return -1;
}

aocio.h 工具头文件代码

//
// Created by gusta on 2022-12-01.
//

#ifndef ADVENTOFCODE_AOCIO_H
#define ADVENTOFCODE_AOCIO_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define SIGN_ASCII 45
#define TRUE 1
#define FALSE 0

#endif //ADVENTOFCODE_AOCIO_H
#define STRING_END '\0'
#define NUMBERS_ASCII 48



char* prompt(const char* question) {
    printf(question);

    char* string = malloc(1);
    int curChar = 0, index = 0;
    while (curChar != '\n') {
        curChar = getchar();
        if (curChar == '\n'){
            string[index] = STRING_END;
        }
        else{
            if (index > 0) {
                string = (char*) realloc(string, index+1);
            }
            string[index] = curChar;
        }
        index++;
    }
    return string;

}

FILE* openFile(const char* fileName) {
    FILE *fptr;
    fptr = fopen(fileName, "r");
    if (fptr == NULL) {
        printf("Big fat file error!!\n");
        fclose(fptr);
        getchar();
        exit(-1);
    }

    return fptr;
}

char readLine(FILE* fptr, char** line) {
    int index = 0, end = 0;
    char* string = (char *) malloc(1);
    char curChar;

    do {
        end = fscanf(fptr, "%c", &curChar);

        if (end == EOF) {
            string[index] = STRING_END;
            fclose(fptr);
            *line = string;
            return FALSE;
        }

        if (curChar == '\n') {
            string[index] = STRING_END;
            *line = string;
            return TRUE;
        }
        else {
            if (index > 0) {
                string = (char *) realloc(string, index + 1);
            }
            string[index] = curChar;
            index++;
        }
    } while (end != EOF);
}

int parseToInt(char* string) {

    int numberLength = 0, number = 0;
    int sign = FALSE;

    for (int index = 0; string[index] != STRING_END; index++) {
        numberLength++;
    }

    for (int index = numberLength-1; index >= 0; index--) {

        char curChar = string[index];
        if (index == 0 && curChar - SIGN_ASCII == 0) {
            sign = TRUE;
            continue;
        }
        if (curChar - NUMBERS_ASCII >= 0 && curChar - NUMBERS_ASCII <= 9) {
            int num = (int) (curChar - NUMBERS_ASCII);
            num *= (int)(pow(10, numberLength-index-1));
            number += num;
        }
        else {
            printf("Felaktig inmatning. parseInt kan bara ta in tal"); // Invalid input. parseInt can only take in numbers
            getchar();
            exit(-1);
        }
    }
    if (sign == TRUE) {
        number *= -1;
    }
    return number;
}

问题根源及修复方案

1. 栈溢出:变长数组(VLA)的危险用法

getDuplicate函数中使用了char letters[length/2];这种变长数组,栈的默认空间通常只有几MB,一旦输入的行长度较大,这个数组会直接耗尽栈空间导致崩溃。Debug模式下IDE可能会给栈分配更大的空间或者添加保护机制,所以不会触发问题,但Release模式下会直接报错。

修复方案:改用堆内存分配,用完后释放:

char getDuplicate(char* line) {
    unsigned int length = strlen(line);
    // 用malloc分配堆内存
    char* letters = malloc(length/2);
    if (letters == NULL) {
        // 处理内存分配失败的情况
        return STRING_END;
    }
    char* cp = letters;

    for (int i = 0; i < length/2; i++) {
        letters[i] = ' ';
    }

    // ... 原有逻辑不变 ...

    // 函数结束前释放内存
    free(letters);
    // 必须添加默认返回值
    return STRING_END;
}

2. 函数缺少默认返回值

getDuplicate函数声明返回char,但如果遍历完整个字符串都没找到重复字符,函数没有任何返回语句,这会导致未定义行为。Debug模式下编译器可能会自动填充一个默认值,但Release模式下会引发不可预测的结果,甚至崩溃。

修复方案:在函数末尾添加明确的默认返回值,比如return STRING_END;。

3. 内存泄漏

readLine函数每次都会通过malloc分配新的字符串,但主程序中从未调用free(line)释放内存。虽然这不是当前崩溃的直接原因,但长期运行会耗尽堆内存,必须修复。

修复方案:在循环内读完每一行后释放内存:

while (readLine(fptr, &line)) {
    char c = getDuplicate(line);
    putchar(c);
    free(line); // 释放当前行的内存
}

4. openFile函数的错误处理bug

当fopen失败时,fptr为NULL,此时调用fclose(fptr)会触发崩溃,因为不能关闭空指针。

修复方案:删除错误分支中的fclose(fptr)语句:

FILE* openFile(const char* fileName) {
    FILE *fptr;
    fptr = fopen(fileName, "r");
    if (fptr == NULL) {
        printf("Big fat file error!!\n");
        // 删除这行:fclose(fptr);
        getchar();
        exit(-1);
    }
    return fptr;
}

5. readLine的realloc逻辑优化

当前readLine中,当index=0时,第一次分配1字节是没问题的,但后续的realloc逻辑可以更稳妥,确保每次分配的空间足够容纳当前字符和终止符。建议修改为每次分配index+2的空间(留一个位置给STRING_END):

else {
    // 不管index是否为0,都重新分配足够的空间
    string = (char *) realloc(string, index + 2);
    string[index] = curChar;
    index++;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:25:29