C:使用动态内存分配存储元素时堆缓冲区溢出

C: Heap Buffer Overflow when Storing Elements Using Dynamic Memory Allocation

提问人:Akiyuu 提问时间:11/19/2022 最后编辑:Akiyuu 更新时间:11/19/2022 访问量:113

问:

我正在编写一个 C 程序来存储,然后使用动态内存分配打印出通过 stdin 给出的所有字符串。 它会提示用户输入,直到它读取“文件末尾”(EOF、ctrl + d)。 我假设没有一行长度超过 255 个字符。

我对 C 编码相对较新,对使用 malloc() 函数也很陌生,所以如果我犯了一些明显的菜鸟错误,请耐心等待。请提供建议并帮助我修复我的程序。:)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER 255

int main(void) 
{
    
    char line[BUFFER];
    int item = 0;
    char** data = malloc(sizeof(char*));
    
    for(;;)
    {
        printf("Enter string %d: ", item + 1);

        if (fgets(line, BUFFER, stdin) == NULL)
        {
            break;
        }

        else
        {
            fgets(line, BUFFER, stdin);
        }

        data = realloc(data, sizeof(void *) * (item + 1));
        data[item] = malloc(sizeof(char) * strlen(line));
        memcpy(data[item], line, strlen(line));

        item++;

    }
    
    printf("\n\nElements:\n");
    
    for(int j = 0; j < item; j++)
    {
        printf("%s",data[j]);

        free(data[j]);
    }

    free(data);

    return 0;
}

我首先担心的是,我的程序会提示用户每次增量输入一个字符串输入两次。这不应该发生,并且应该在更新 的计数时不断询问用户。itemitem

此外,我的程序没有存储正确输入的字符串;当尝试访问和打印我存储的字符串时,它会返回缓冲区溢出消息。我以前从未见过类似的错误:

==20==错误:AddressSanitizer:地址0x602000000052在 pc 0x55a8453c7865 bp 0x7ffd578edac0 sp 0x7ffd578ed280 上堆缓冲区溢出 在螺纹 T0 处读取尺寸 3 0x602000000052 #0 0x55a8453c7864 in printf_common(void*, char const*, __va_list_tag*) asan_interceptors.cpp.o #1 __interceptor_vprintf 中的0x55a8453c819a (/home/run+0xb119a) (BuildId: abfaad925a09237bc199a1c2ac9a7d328268e42f) #2 printf 中的0x55a8453c8277 (/home/run+0xb1277) (BuildId: abfaad925a09237bc199a1c2ac9a7d328268e42f) #3 在 main /home/main.c:39:9 中0x55a84543014d #4 0x7f08c84fe28f __libc_start_call_main /usr/src/debug/glibc/csu/ 中。/sysdeps/nptl/libc_start_call_main.h:58:16 #5 __libc_start_main /usr/src/debug/glibc/csu/ 中的0x7f08c84fe349。/csu/libc-start.c:381:3 #6 _start /build/glibc/src/glibc/csu/ 中的0x55a845337084。/sysdeps/x86_64/start。小号:115

C 字符串 动态 malloc 缓冲区溢出

评论

0赞 Akiyuu 11/19/2022
@user3121023我已经更改了这条线,但问题仍然存在。不过,谢谢你指出来!
0赞 Andrew Henle 11/19/2022
@Akiyuu 您还需要终止字符串。 是不够的。替换为 .data[item] = malloc(sizeof(char) * ( strlen(line) + 1));memcpy()strcpy()
0赞 Akiyuu 11/19/2022
@user3121023这两个更改实际上完全修复了我的代码!非常感谢你:D

答:

1赞 user3121023 11/19/2022 #1

getline当最长行的长度未知时很有用。它将根据需要分配内存。它还返回已处理的字符数。
最好重新分配给临时指针。如果失败,则原始指针仍然有效。
realloc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( void) {

    char *line;
    size_t size = 0;
    ssize_t length = 0;
    int item = 0;
    char** data = NULL;

    for ( ; ; ) {
        printf ( "Enter string %d: ", item + 1);
        fflush ( stdout);

        if ( 0 > ( length = getline ( &line, &size, stdin))) {
            break;
        }

        char **temp = NULL;
        if ( NULL == ( temp = realloc ( data, sizeof *data * (item + 1)))) {
            fprintf ( stderr, "realloc problem\n");
            break;
        }
        data = temp;
        if ( NULL == ( data[item] = malloc ( sizeof **data * ( length + 1)))) {
            fprintf ( stderr, "malloc problem\n");
            break;
        }

        strcpy ( data[item], line);

        item++;
    }

    free ( line);

    printf("\n\nElements:\n");

    for(int j = 0; j < item; j++) {
        if ( data[j] && data[j][0]) { // not NULL and not zero
            printf ( "%s", data[j]);
        }
        free(data[j]);
    }
    free(data);

    return 0;
}