世界!我不擅长动态内存分配,所以请帮助我!问题是,当我在不使用消毒剂的情况下编译c文件时,它会正常执行。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str = (char *)malloc(sizeof(char));
int i = 1;
while (str[i - 2] != '\n')
{
str = (char *)realloc(str, i * sizeof(char));
str[i - 1] = getchar();
i++;
}
str[++i] = '\0';
fputs(str, stdout);
free(str);
return 0;
}
这是消毒剂说的:
==7174==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000000f at pc 0x55739456b340 bp 0x7fffba0090f0 sp 0x7fffba0090e0
READ of size 1 at 0x60200000000f thread T0
#0 0x55739456b33f in main (/home/bek/diff1+0x133f)
#1 0x7fd15ff780b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#2 0x55739456b1ad in _start (/home/bek/diff1+0x11ad)
0x60200000000f is located 1 bytes to the left of 1-byte region [0x602000000010,0x602000000011)
allocated by thread T0 here:
#0 0x7fd160250bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x55739456b27e in main (/home/bek/diff1+0x127e)
#2 0x7fd15ff780b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/bek/diff1+0x133f) in main
答案 0 :(得分:3)
您有问题
while (str[i - 2] != '\n')
对于第一次迭代,i
是1
,因此索引值为-1
,这是无效的索引。
那是另外一些重要的事情:
由malloc()
返回的内存未初始化。如果尝试在将任何值分配给内存之前先读取它,则会被不确定的值打中,并且程序的行为是不可预测的。
语法
str = (char *)realloc(str, i * sizeof(char));
这是一个非常有问题的问题,万一realloc()
失败并返回NULL
,您也将失去原始指针!
在将返回值分配给变量之前,始终检查realloc()
调用是否成功,例如
char * tmp = NULL;
tmp = realloc(str, i); // cast not needed, sizeof(char) == 1 in C
if (!tmp) { exit(1); /* or cleanup*/}
str = tmp; // assign otherwise
Please see this discussion on why not to cast the return value of malloc() and family in C..
答案 1 :(得分:1)
由于您使用的是POSIX系统,因此只需使用轮子而不是重新发明轮子即可。
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
int main(void) {
char *str = NULL;
size_t n = 0;
ssize_t result = getline(&str, &n, stdin);
if (result < 0) {
perror("An error occurred in getline");
exit(1);
}
fputs(str, stdout);
free(str);
}
如果您需要尝试使用较小的系统,则仅使用标准C库工具就可以实现许多标准getline
的实现。