从stringstream复制到char *数组作为函数参数返回

时间:2012-05-17 00:23:23

标签: c++ memory-management char winsock stringstream

我正在使用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;
}

2 个答案:

答案 0 :(得分:3)

resphttp_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::stringboost::asio,则不会再遇到内存管理问题。