了解何时需要 malloc():我在编译时知道 char * n 的长度,但似乎仍然需要 malloc()
Posted
技术标签:
【中文标题】了解何时需要 malloc():我在编译时知道 char * n 的长度,但似乎仍然需要 malloc()【英文标题】:Understanding when malloc() is necessary: I know the length of char * n at compile time yet still seem to need malloc() 【发布时间】: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,因此最糟糕的情况是文件名被截断(找不到)而不是堆栈损坏。
【参考方案1】:
char *filename[8];
好的,所以我们声明一个包含 8 个字符指针的数组,不初始化任何指针,并将一个传递给 sprintf
目标。
你的工作代码是
char *filename = malloc(8);
它清楚地声明了一个指针,并用指向堆外 8 个字节的指针对其进行初始化。因此,你想要
char filename[8];
声明一个 8 个字符的数组。
【讨论】:
以上是关于了解何时需要 malloc():我在编译时知道 char * n 的长度,但似乎仍然需要 malloc()的主要内容,如果未能解决你的问题,请参考以下文章