我该如何解决 `malloc(): corrupted top size`?
我在尝试用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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。