[英]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.