简体   繁体   English

C:通过使用realloc导致内存错误

[英]C: memory error by using realloc

Considering the toy-code as follows: 考虑玩具代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LENGTH (5000)

typedef struct request_body_s {
    char *data;
    size_t size;    // in bytes
} request_body_t;

int do_something(request_body_t *request_body) {
    char* content = read_content_elsewhere("/dir/content");
    size_t size = strlen(content) * sizeof(char);
    request_body->data = (char *) realloc(request_body->data, size + 1);
    if (request_body->data == NULL)
        return 0;
    else {
        request_body->size = size;
        strncpy(request_body->data, content, MAX_STRING_LENGTH);
        return 1;
    }
}

int main(int argc, char *argv[]) {
    request_body_t request_body;
    request_body.data = malloc(1);
    request_body.size = 0;

    if (do_something(&request_body))
        printf("Read!\n");
    else {
        printf("Error!\n");
        exit(0);
    }

    free(request_body.data);
    request_body.size = 0;
}

This code seems work fine until free(request_body.data) is called; 直到调用free(request_body.data)这段代码才能正常工作。 it generates an error as follows: 它产生如下错误:

*** free(): invalid next size (fast): 0x0000000001594570 ***

What is (of course) wrong and why? (当然)有什么错误,为什么? Thanks for any suggestion. 感谢您的任何建议。

I believe the issue is right here: 我相信问题就在这里:

 strncpy(request_body->data, content, MAX_STRING_LENGTH);

depending on your goal (not clear from your description), I would suggest: 根据您的目标(不清楚您的描述),我建议:

strncpy(request_body->data, content, size > MAX_STRING_LENGTH ? MAX_STRING_LENGTH : size );

strncpy copies the first n chars of the string, that is 5000 in your case. strncpy复制字符串的前n个字符,在您的情况下为5000。 If the source string is smaller that n (5000 here), the rest is padded with zeros, therefore you are accessing further that the end of your bufffer, which leads to undefined behaviour. 如果源字符串小于n (此处为5000),则其余部分将填充零,因此您将进一步访问bufffer的末尾,这将导致不确定的行为。

You need: 你需要:

strcpy(request_body->data, content);

It is safe here to use strcpy because we can be sure that the memory allocated by realloc is large enough, because you realloc strlen(content) + 1 chars. 它这里是安全使用strcpy ,因为我们可以肯定的是由分配的内存realloc是足够大的,因为你realloc strlen(content) + 1个字符。

BTW * sizeof(char) is always 1 by definition, so the * sizeof(char) is not necessary. BTW * sizeof(char)根据定义始终为1,因此* sizeof(char)并非必需。

As written in the strncpy manual , strncpy手册中所述

If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total of n bytes are written. 如果src的长度小于n,则strncpy()将其他空字节写入dest以确保总共写入n个字节。

So, by using strncpy(request_body->data, content, 5000); 因此,通过使用strncpy(request_body->data, content, 5000); , you write many '\\0' outside your buffer. ,则在缓冲区外写了许多'\\ 0'。 You shouldn't ever do that , it's an undefined behaviour, and, in this case, you're writing on the 'metadata' used by free , so it crashes. 永远不要这样做 ,这是不确定的行为,在这种情况下,您正在写free使用的“元数据”,因此它崩溃了。

Here, it would be preferable to use strcpy (and make sure to add a '\\0' at the end), or memcpy , because you know the size you want to write. 在这里,最好使用strcpy (并确保在末尾添加“ \\ 0”)或memcpy ,因为您知道要编写的大小。

Also, casting the return of malloc is useless , and sizeof(char) is and will very probably always be 1, so it's also useless. 另外, 强制转换malloc的返回是无用的 ,并且sizeof(char)且将很可能始终为1,因此它也是无用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM