我正在使用Winsock2试验HTTP协议。我正在开发一个函数
int recv_data(const char * hostname,char * resp);
该函数用于向给定主机发送HTTP HEAD请求,然后接收响应。它在指针resp处分配了内存,并在返回响应的总字节数之前复制响应。
这是我的接收循环:
int recv_data(const char *hostname, char *resp)
{
int totalRecvd = 0;
stringstream sStream;
while (true)
{
char buffer[MAX_HEADER_SIZE];
int retValue = recv(s, buffer, MAX_HEADER_SIZE, 0);
if (retValue == 0)
break; // connection has been closed
else if (retValue == SOCKET_ERROR)
throw RecvException("http_headreq() unable to receive data");
else //
{
buffer[retValue] = 0; // append null terminator
sStream << buffer; // dump buffer into stream
totalRecvd += retValue + 1; // tally received bytes
}
}
/** Allocate and read entire read stream into memory */
resp = new char[totalRecvd + 1];
strcpy(resp, sStream.str().c_str());
return totalRecvd);
}
所有这一切都很好,所有这一切,如果我输出resp此时输出就好了。如果我在函数显然返回后尝试输出resp,我只会遇到问题。我不相信这应该是通常的事情,如果我没有弄错,我相信它与我使用stringstream临时存储响应有关。我想我已经读过有关stringstream收集的超出范围的数据。
我希望我可以通过这种方式设置此函数,其中调用者只需传入一个char *,该函数将分配正确的内存量(在运行时根据主机和数量确定) recv()返回的字节。无论如何,我是否从内存中的字符串流中获取永久副本作为char数组,在函数返回并且字符串流超出范围后指针变坏?
[编辑]:下面发布的解决方案包含在我的问题中,任何想要重复使用Winsock2 proramming的人都有,似乎运行良好。当recv()返回0时,将从服务器recv数据,直到连接关闭。解决方案是传入对指针的引用,因为new运算符更改指针,并且在函数返回后不会反映该更改,除非它被传递通过引用。
int recv_data(SOCKET s, char *&data)
{
int totalRecvd = 0;
std::stringstream sStream;
while (true)
{
char buffer[MAX_HEADER_SIZE];
int retValue = recv(s, buffer, MAX_HEADER_SIZE, 0);
if (retValue == 0)
break; // connection has been closed
else if (retValue == SOCKET_ERROR)
throw RecvException("http_headreq() unable to receive data");
else //
{
buffer[retValue] = 0; // append null terminator
sStream << buffer; // dump buffer into stream
totalRecvd += retValue + 1; // tally received bytes
}
}
/** Allocate and read entire read stream into memory */
data = new char[totalRecvd + 1];
strcpy_s(data, totalRecvd, sStream.str().c_str());
data[totalRecvd] = 0;
return totalRecvd;
}
答案 0 :(得分:3)
resp
是http_req
函数中的局部变量。更新resp
的值不会在http_req
之外生效。这一行:
resp = new char[totalRecvd + 1];
只会产生局部效果。
尝试此签名:
int http_req(const char *hostname, char *&resp);
<小时/> 更好的是,尝试以C ++方式返回数据:
std::string http_req(const std::string& hostname) {
...
return sStream.str()
}
答案 1 :(得分:0)
如果您更改代码以使用std::string
和boost::asio
,则不会再遇到内存管理问题。