【发布时间】:2014-04-06 07:07:26
【问题描述】:
我正在开发一个 C 代码来执行 GET 请求并处理可变大小的响应。
我使用 realloc 来调整我存储响应的堆块的大小。问题是我收到了与 realloc 调用的 CrtIsValidHeapPointer 函数相关的错误。
循环运行了 6 次,但在第 7 次循环时出现错误。 我这里有你的代码:
#include "stdafx.h"
using namespace std;
int GET_request(char *hostname, char *path);
char *scat(char *, char *);
int _tmain(int argc, _TCHAR* argv[])
{
GET_request("www.marca.com", "/");
}
int GET_request(char *hostname, char *path){
char request[256];
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("WSAStartup failed.\n");
system("pause");
return 1;
}
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host;
host = gethostbyname(hostname);
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
printf("Connecting...\n");
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){
printf("Could not connect");
system("pause");
return 1;
}
printf("Connected.\n");
if ((strlen(hostname) + strlen(path)) > 197)
{
printf("Lenght too long for a GET path");
return 1;
}
else
{
const char *method = "GET ";
strcpy_s(request, method);
strcat_s(request, path);
strcat_s(request, " HTTP/1.1\r\n");
strcat_s(request, "Host: ");
strcat_s(request, hostname);
strcat_s(request, "\r\n");
strcat_s(request, "Connection: close\r\n\r\n");
}
//printf_s(request);
int len;
len = strlen(request);
system("pause");
send(Socket, request, strlen(request), 0);
char *ptr = (char*)calloc(sizeof(char),1024);
char *ptr2 = NULL;
int nDataLength;
int i = 0;
while ((nDataLength = recv(Socket, ptr, 1023, 0)) > 0){
if (i > 0){//prepare in case that the response is bigger than 1024 bytes
//printf("Data len: %d\n", nDataLength);
//system("pause");
printf("%p apunta a %d len: %d e i vale: %d\n", ptr2, *ptr2, ((1023 * i) + nDataLength), i);
system("pause");
ptr2 = (char*)realloc(ptr2, ((1023 * i) + nDataLength));
if (ptr2==NULL){
printf("Some error reallocating memory\n");
system("pause");
i++;
}
else{
memcpy(ptr2 + (1024 * i), ptr, nDataLength);
//printf("%s\n", ptr2);
//system("pause");
i++;
}
}
else{
ptr2 = (char*)realloc(ptr2, ((1023 * i) + nDataLength));
memcpy(ptr2, ptr, nDataLength);
i++;
}
}
printf("%s",ptr2);
system("pause");
closesocket(Socket);
WSACleanup();
system("pause");
FILE* pFile;
pFile = fopen("myfile.txt", "wb");
fwrite(ptr2, 1, strlen(ptr2), pFile);
fclose(pFile);
free(ptr2);
return 0;
}
您可以检查while 循环。我只是想给你所有的代码,以防你想尝试它。
我得到了这个:
Connecting...
Connected.
Press any key to continue . . .
0033D500 apunta a 72 len: 2046 e i vale: 1
Press any key to continue . . .
0033D500 apunta a 72 len: 3069 e i vale: 2
Press any key to continue . . .
0033D500 apunta a 72 len: 4092 e i vale: 3
Press any key to continue . . .
0033D500 apunta a 72 len: 5115 e i vale: 4
Press any key to continue . . .
0033D500 apunta a 72 len: 6138 e i vale: 5
Press any key to continue . . .
0033D500 apunta a 72 len: 7161 e i vale: 6
Press any key to continue . . .
谢谢
【问题讨论】:
-
您无需读取套接字即可测试该 realloc 循环。只需从文件中提取数据。而且您的指针数学似乎不正确,至少在其他条件下。您正在读取 1023 字节的块,始终将最后一个插槽保存为终结符,但其他插槽从
(i*1024)开始。每次迭代时,您都会将i插槽移出分配范围并移至 UB。最后,这与 C++ at all 有什么关系?如果您使用 C++,请使用向量并将所有这些realloc垃圾扔掉;否则会丢失 C++ 标签。
标签: c memory-management malloc realloc