我一直在写一个虚拟机,我注意到发生了一些奇怪的事情,尽管我很久以前写过这个函数。无论如何,我的虚拟机会读取这样的文件:
0002 000A 0001 0004 0000
然而,当我不在0000或新行之后有任何空格时......它会崩溃。另一个非常奇怪的事情,让我相信它是不文件加载,是当你从文件中删除0000
时,空格......它有效吗?!我试过通过GDB运行它,但它确实有效 - 显然这被称为heisenbug或其他东西。我认为这是由于文件的加载方式,您可以在this function here on github中看到,或者只是阅读下面的代码段。
void load_program(vm *self) {
FILE *file = fopen("testing.ayy", "r");
if (file != NULL) {
if (fseek(file, 0, SEEK_END) == 0) {
long file_size = ftell(file);
if (file_size == -1) {
perror("could not read filesize\n");
exit(1);
}
self->source = malloc(sizeof(char) * file_size);
if (fseek(file, 0, SEEK_SET) != 0) {
perror("could not reset file index\n");
exit(1);
}
size_t file_length = fread(self->source, sizeof(char), file_size, file);
if (file_length == 0) {
perror("given file is empty\n");
exit(1);
}
self->source[file_size] = '\0';
}
fclose(file);
}
else {
perror("could not read file: \n");
exit(1);
}
self->source_compact = strdup(self->source);
self->source_compact = deblank(self->source_compact);
// here we divide because strlen is in characters,
// whereas each instruction code should be 4 characters
// so we're converting char size to num of instructions
self->instructions_size = strlen(self->source_compact) / INSTRUCTION_LENGTH;
int i;
for (i = 0; i < self->instructions_size; i++) {
char *instr = substring(self->source_compact, i);
if (strcmp(instr, ERROR_CODE)) { // not equal to NOPE
if (self->instructions != NULL) {
self->instructions = add_instructions(self->instructions, strtol(instr, NULL, 16));
}
else {
self->instructions = create_instructions(strtol(instr, NULL, 16));
}
}
}
self->instructions = reverse(self->instructions);
}
但是我添加了一个GitHub链接,因为我不确定它是否是那个功能;或者如果它是由于整个来源发生的任何事情 - 所以如果任何C大师可以帮助我,那将是辉煌的:)。我确定它位于vm.c
或vm.h
,并且对于可怕的代码感到抱歉;我在学习时从未真正关注过File IO(大错误)。
答案 0 :(得分:1)
self->source = malloc(sizeof(char) * file_size); ... self->source[file_size] = '\0';
您需要为终止零分配一个字节。索引source[file_size]
实际上是超出分配内存末尾的一个字节。写入该位置可能会破坏malloc()
使用的其他变量或内部结构。成功:
self->source = malloc(sizeof(char) * (file_size + 1));
或只是:
self->source = malloc(file_size + 1);
sizeof(char)
始终为1
,因此它是多余的。
如果您希望在self->source
的类型发生变化时保护自己,可以使用:
self->source = malloc ((file_size+1) * sizeof *self->source);
自动分配正确的大小。
在尝试访问内存之前,您还应该检查分配是否成功。