尝试重新分配内存时,使用此代码时崩溃:
//value of i is currently 4096
while((c = recv(sock, htmlbff + q, MAXDATASIZE, 0)) > 0)
{
if((i - q) < MAXDATASIZE)
{
i *= 2;
if(!(tmp = realloc(htmlbff, i)))
{
free(htmlbff);
printf("\nError! Memory allocation failed!");
return 0x00;
}
htmlbff = tmp;
}
q += c;
}
由于内存泄漏而崩溃....但是以下代码不会崩溃:
while((c = recv(sock, htmlbff + q, MAXDATASIZE, 0)) > 0)
{
if((i - q) < MAXDATASIZE)
{
i *= 2;
if(!(tmp = realloc(htmlbff, i)))
{
free(htmlbff);
printf("\nError! Memory allocation failed!");
return 0x00;
}
}
htmlbff = tmp;
q += c;
}
如何在if语句之外移动htmlbff = tmp;
来解决这个问题?在if语句中,似乎没有将htmlbff
设置为tmp
...我非常困惑。
答案 0 :(得分:3)
/*
* I assume these exist, and more or less fit the requirements described.
* They don't have to be these specific numbers, but they do need to have
* the specified relationships in order for the code to work properly.
*/
#define MAXDATASIZE 4096 /* any number here is ok, subject to rules below */
int i = 4096; // i >= MAXDATASIZE, or the first recv can trigger UB
char *htmlbff = malloc(i); // ITYK you can't realloc memory that wasn't malloc'd
int q = 0; // q <= i-MAXDATASIZE
/* maybe other code */
while((c = recv(sock, htmlbff + q, MAXDATASIZE, 0)) > 0)
{
/*
* You've already just read up to MAXDATASIZE bytes.
* if (i-q) < MAXDATASIZE, then **your buffer is already too small**
* and that last `recv` may have overrun it.
*/
if((i - q) < MAXDATASIZE)
{
... reallocate htmlbff ...
}
/* Then you bump q...but too late. lemme explain in a sec */
q += c;
}
假设您连续两次收回4096个字节。会发生什么:
htmlbff + 0
开始读取4096个字节。q
仍为0,i - q
== 4096,因此不会进行任何分配。q
被4096提升了。htmlbff + 4096
开始获得4096字节。但是等等,因为我们没有在最后一次迭代时调整它,htmlbff
只有4096字节大,并且整个读取溢出缓冲区! 试试这个......
while((c = recv(sock, htmlbff + q, MAXDATASIZE, 0)) > 0)
{
/* **First**, bump `q` past the stuff you just read */
q += c;
/*
* **Now** check the buffer. If i-q is too small at this point, the buffer is
* legitimately too small for the next read, and also hasn't been overrun yet.
*/
if((i - q) < MAXDATASIZE)
{
/* This temp pointer **really** should be limited in scope */
char *double_sized;
/* Note that otherwise, i'm using the "broken" resize code.
* It should work fine.
*/
i *= 2;
if(!(double_sized = realloc(htmlbff, i)))
{
free(htmlbff);
printf("\nError! Memory allocation failed!");
return 0x00;
}
htmlbff = double_sized;
}
}
答案 1 :(得分:1)
您不能使用小于数据的缓冲区接收数据,然后重新分配它以适应更大的数据。
您需要重写代码:
buffer = malloc(MAXDATASIZE)
size_t received = 0
while ((size_t sz = recv(sock, buffer+received, MAXDATASIZE-received, 0) > 0)
{
received += sz
}
buffer = realloc(buffer, received);
我更改了变量名称,并且详细说明。您的代码奇怪的行为可能是随机的,两个代码都是错误的。您可以在此处了解详情:http://en.wikipedia.org/wiki/C_dynamic_memory_allocation