【问题标题】:it works fine without AddressSanitizer没有 AddressSanitizer 也能正常工作
【发布时间】:2021-01-22 02:40:26
【问题描述】:

世界!我不擅长动态内存分配,所以请帮助我!问题是当我在没有消毒剂的情况下编译 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

【问题讨论】:

  • 总是为缓冲区重新分配一个字节似乎相当低效。您可能需要先重新考虑这种方法。
  • 您可能需要char c = getchar(); if(c == '\n') break; 之类的东西来避免@SouravGhosh 发现的有问题的if 语句。
  • @AKX int c :D
  • @AnttiHaapala 当然,忘记了 Dre EOF。

标签: arrays c pointers dynamic-memory-allocation


【解决方案1】:

你有问题

 while (str[i - 2] != '\n')

对于第一次迭代,i1,因此索引值为 -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..

【讨论】:

    【解决方案2】:

    由于您使用的是 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);
    }
    

    如果您需要冒险使用较小的系统,标准 getline 的许多实现只使用标准 C 库工具。

    【讨论】:

    猜你喜欢
    • 2014-12-25
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 2021-01-28
    • 2016-08-11
    • 1970-01-01
    相关资源
    最近更新 更多