我该如何解决 `malloc(): corrupted top size`?

编程语言 2026-07-12

我在尝试用C 语言构建一个符号表。下面是代码的摘录:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TYPE_A 0
#define TYPE_C 1
#define TYPE_L 2


typedef struct {
    char* symbol;
    int address;
} SYMBOLS;


SYMBOLS** addEntry(char* symbol, int line, SYMBOLS** table, int* totalCount) {
    SYMBOLS* newEntry = malloc(sizeof(SYMBOLS));
    newEntry->symbol = strdup(symbol);
    newEntry->address = line;
    table[*totalCount] = newEntry;
    (*totalCount)++;
    return table;
}

SYMBOLS** initSymbol(int capacity, int* totalCount) {
    SYMBOLS** table = malloc(sizeof(SYMBOLS*) * capacity);
    return table;
}

char* cleanLine(char* d, FILE* fp) {
    char* c = strdup(d);
    while (*c == ' ' || *c == '/' || *c == '\n') {
        if (*c == ' ') c++;
        if (*c == '/' || *c == '\n') {
            if (fgets(c, 100, fp) == NULL) return NULL;
        }
    }
    char* end = c;
    while (*end != '\n') end++;
    while (*(end-1) == ' ') end--;
    *end = '\0';
    return c;
}


int instructionType(char* c) {
    if (*c == '(') return TYPE_L;
    else if (*c == '@') return TYPE_A;
    else return TYPE_C;
}


int main(int argc, char* argv[]) {
    if (argc >= 2) {
        FILE* fp = fopen("test.asm", "r");

        char* instruction = malloc(sizeof(char) * 100);

        int capacity = 1000;
        int* totalCount = malloc(sizeof(int));
        *totalCount = 0;
        SYMBOLS** table = initSymbol(capacity, totalCount);
        printf("asdf\n");

        while (fgets(instruction, 100, fp) != NULL) {
            instruction = cleanLine(instruction, fp);
            printf("%s\n", instruction);
            int type = instructionType(instruction);
            printf("%d\n", type);
            printf("sdfj");

        }
    }
    return 0;
}

然而,当我执行这段代码时,返回 malloc(): corrupted top size 错误。我在代码中放了一些printf,用来排查是哪一部分在引发错误,结果出乎意料地,显示 type 值的那条能够工作,而紧随其后的那条("sdfj")却无法工作。我完全不知道为什么连续两个 printf 会无法正确工作。

我认为没有变量在访问分配内存之外的区域,所有变量都在 main 函数内可访问。

有什么错误吗?

这是我用于测试的文件:

// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/6/rect/Rect.asm

// Draws a rectangle at the top-left corner of the screen.
// The rectangle is 16 pixels wide and R0 pixels high.
// Usage: Before executing, put a value in R0.

   // If (R0 <= 0) goto END else n = R0
   @R0
   D=M

(以上文件来自Nand2Tetris,所有权利归该项目所有)

解决方案

这里有两个主要问题。

首先,当在 cleanLine 调用 fgets 时,你是在告诉 fgets 缓冲区的宽度为100字节,而实际缓冲区的大小取决于传入字符串的长度。因此如果读取的内容超过该长度,你就会写到已分配内存的边界之外。这会触发未定义行为 undefined behavior,在你的情况下(幸运地)导致了崩溃。

不要使用 strdup,改用malloc创建一个合适大小的缓冲区,再用 strcpy 进行拷贝:

char* c = malloc(100);
strcpy(c,d);

其次,在 cleanLine 返回NULL的情况下,后续的指令将尝试读取该NULL指针,这也会造成未定义行为。你需要在这种情况下跳出循环:

instruction = cleanLine(instruction, fp);
if (!instruction) break;

请注意,这并未解决任何内存泄漏问题。留给读者自行练习。Valgrind对发现内存泄漏和无效内存访问都很有帮助。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章