【发布时间】:2019-11-23 12:23:33
【问题描述】:
我是学习 C 的初学者。例如,根据我所学和阅读的 here,当您不知道编译时所需的内存量时,您可以使用 malloc()。我正在编写代码,其中我知道我要声明的字符串的长度,但是如果我不使用 malloc() 分配内存并且我不明白为什么会出现错误。
我正在编写的代码是针对哈佛 CS50 问题集,其中目标是恢复已删除的 jpg,但我已将其剥离以仅显示此问题。我的代码显示了两行声明 char* 文件名的行,其中导致错误的行被注释掉了。两个选项都会编译,没有 malloc() 的选项会在运行时导致 UndefinedBehaviorSanitizer:DEADLYSIGNAL 错误。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// remember filenames
char *infile = argv[1];
//open input file
FILE *inptr = fopen(infile, "r");
//buffer
BYTE buffer[512];
//read first 512 byte block in to buffer
size_t r = fread(&buffer, 1, 512, inptr);
int n = 0;
//get name for new jpg file
//char *filename[8]; //<<<<<<<<<<<<<<<<<<<<<this causes error
char *filename = malloc(8);
sprintf(filename, "%03i.jpg", n);
}
这是错误:
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==5563==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7fb433fba0ac bp 0x000000000030 sp 0x7ffd5af8a290 T5563)
==5563==The signal is caused by a WRITE memory access.
==5563==Hint: address points to the zero page.
#0 0x7fb433fba0ab (/lib/x86_64-linux-gnu/libc.so.6+0x900ab)
#1 0x7fb433fb8493 (/lib/x86_64-linux-gnu/libc.so.6+0x8e493)
#2 0x7fb433faa37d (/lib/x86_64-linux-gnu/libc.so.6+0x8037d)
#3 0x7fb433f86f1f (/lib/x86_64-linux-gnu/libc.so.6+0x5cf1f)
#4 0x7fb433fab6d0 (/lib/x86_64-linux-gnu/libc.so.6+0x816d0)
#5 0x7fb433f8f093 (/lib/x86_64-linux-gnu/libc.so.6+0x65093)
#6 0x428049 (/home/ubuntu/pset3/recover/malloc+0x428049)
#7 0x7fb433f4bb96 (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#8 0x402ad9 (/home/ubuntu/pset3/recover/malloc+0x402ad9)
UndefinedBehaviorSanitizer can not provide additional info.
==5563==ABORTING
【问题讨论】:
-
char *filename[8];创建一个包含 8 个(未初始化)指针的数组。你可能想要char filename[8]; -
char filename[8]将为您创建一个长度为 8 的字符数组。 -
请注意,当
n >= 1000时,sprintf(filename, "%03i.jpg", n);会导致缓冲区溢出,因为'\0'终止符需要空间 -
谢谢pmg 和Taegyung。 char filename[8] 运行时没有错误。该问题仅限于 50 jpg,因此 n 不会超过 50。
-
无论如何,请使用 sprintf,因此最糟糕的情况是文件名被截断(找不到)而不是堆栈损坏。