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

C语言中调用realloc时触发'unknown Signal'异常的问题排查

C语言中调用realloc时触发'unknown Signal'异常的问题排查

我理解你的问题:你在实现Look-and-Say序列的处理函数时,使用realloc动态调整输出缓冲区的内存,结果在分配6365字节时总是崩溃;虽然直接预分配足够空间能正常运行,但你希望找到realloc崩溃的根本原因并修复。我帮你梳理下代码里的关键问题,尤其是导致堆结构破坏进而引发realloc崩溃的核心原因:

1. 崩溃的核心根源:Input缓冲区固定大小导致堆溢出

先看你的main函数里的一个致命错误:

// 初始只给input分配了12字节的固定空间
char *input = malloc(12 * sizeof(char)); 
strcpy(input, "1321131112");

在后续的循环中,你每次把处理后的result(长度会随着Look-and-Say迭代指数增长)直接strcpy到input:

strcpy(input, result);
// free(result); // 被注释未执行

当result的长度超过12字节时,strcpy会直接写入input分配的内存区域之外,这会严重破坏堆的元数据结构。堆结构被破坏后,后续的realloc操作依赖堆的完整性,就会触发未知信号崩溃——这就是你看到“每次分配6365字节时崩溃”的根本原因,此时堆已经被之前的多次缓冲区溢出破坏得无法正常工作了。

2. realloc相关的其他潜在问题

2.1 内存复用的逻辑合理性

你在循环中复用result的内存(每次调用look_and_say时realloc它的空间)这个逻辑本身是没问题的——realloc(NULL, size)等价于malloc(size),后续的realloc会基于已有内存块调整大小。但因为堆被前面的溢出破坏,这个逻辑才会失效。

2.2 函数内的小错误

你的look_and_say函数还有几个不影响崩溃但需要修正的小问题:

  • printf("Input string empty\n");写在return -1;之后,永远不会执行,需要调整顺序:
    if (len == 0) {
        printf("Input string empty\n");
        return -1; // 先打印再返回
    }
    
  • 循环末尾手动添加'\0'是多余的:sprintf会自动在生成的字符串末尾写入终止符,你手动添加会导致new_len多累加1,虽然不会直接出错,但不符合逻辑。

修复方案

方案1:修复Input的动态内存管理

在main的循环中,每次处理完后重新调整input的大小,确保能容纳result的内容:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INPUT_SIZE 20000000 //20'000'000

int main(){
    char *input = malloc(12 * sizeof(char)); 
    if (input == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    strcpy(input, "1321131112");
    char* result = NULL; 

    for(int i = 0; i < 25; i++){
        printf("Input length: %zu __ ", strlen(input));
        int status = look_and_say(&input, &result);
        printf("Output length: %zu \n", strlen(result));
        
        if (status < 0) {
            printf("Error processing input: num: %d status:%d\n", i, status);
            free(input);
            free(result);
            return 1;
        }
        
        // 释放旧的input,重新分配足够容纳result的空间
        free(input);
        input = malloc(strlen(result) + 1);
        if (input == NULL) {
            printf("Input memory allocation failed\n");
            free(result);
            return 1;
        }
        strcpy(input, result);
    }

    printf("Final result length: %zu\n", strlen(result));
    free(result); 
    free(input); 
    return 0;
}

这个修复解决了input缓冲区溢出的问题,堆结构不会再被破坏,realloc就能正常工作了。

方案2:优化look_and_say函数的内存操作

你可以保留realloc的逻辑,同时修正函数内的小问题:

int look_and_say(char** input, char** output) {
    if (input == NULL || *input == NULL) {
        return -1; 
    }
    size_t len = strlen(*input);
    if (len == 0) {
        printf("Input string empty\n");
        return -1; 
    }
    if( len *2 +1 > MAX_INPUT_SIZE){
        printf("Input too large\n");
        return -5; 
    }
    printf("Size to allocate: %zu __ ", len * 2 + 1);

    char* temp_storage = realloc(*output, len * 2 + 1); 
    if (temp_storage == NULL) {
        return -2; 
    }
    *output = temp_storage;

    int count = 1;
    int new_len = 0;
    for(int i = 1; i <= len; i++){
        if(i < len && (*input)[i] == (*input)[i-1]){
            count++;
        } else {
            new_len += sprintf(*output + new_len, "%d%c", count, (*input)[i-1]);
            count = 1; 
        }
    }
    // sprintf已自动写入终止符,无需手动添加
    return 1; 
}

验证效果

修复后,input会动态适配每次的结果长度,不会再发生缓冲区溢出,堆结构保持完整,realloc就能正常调整内存大小,你的函数就能按预期工作了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:38:03