tcp 连接时出现分段错误

问题描述 投票:0回答:1

我编写了一个连接到 TCP 服务器、发送字符串并接收字符串回复的函数。还有一个定义为字符数组的缓冲区,每次都会被清除并填充来自套接字的字符串回复。 这个函数被我的程序中的多个pthread同时调用。问题是它工作正常,但几分钟后,程序崩溃并出现信号11(SIGSEGV)。你能帮我吗?另外,如果有更好的实现,如果您分享,我将不胜感激。

int software::send_tcp_remote_cmd(std::string inputstr, std::string *outputstr, short timeout)
{

    char *serverIp = (char *)config["common"]["rch_ip"].get<std::string>().c_str();
    int port = config["common"]["rch_port"].get<int>();
    // create a message buffer
    char msg[3500] = {'\0'};
    // setup a socket and connection tools
    struct hostent *host = gethostbyname(serverIp);
    sockaddr_in sendSockAddr;
    bzero((char *)&sendSockAddr, sizeof(sendSockAddr));
    sendSockAddr.sin_family = AF_INET;
    sendSockAddr.sin_addr.s_addr =
        inet_addr(inet_ntoa(*(struct in_addr *)*host->h_addr_list));
    sendSockAddr.sin_port = htons(port);
    int clientSd = socket(AF_INET, SOCK_STREAM, 0);
    struct timeval tv;
    tv.tv_sec = timeout;
    tv.tv_usec = 0;
    setsockopt(clientSd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv);
    // try to connect...
    int status = connect(clientSd,
                         (sockaddr *)&sendSockAddr, sizeof(sendSockAddr));
    if (status < 0)
    {
        cout << "send_tcp_remote_cmd : Error connecting to socket!" << endl;
        return -1;
    }
    int bytesRead = 0;
    int bytesWritten = 0;
    memset(&msg, 0, sizeof(char)*3500); // clear the buffer
    strcpy(msg, inputstr.c_str());
   spdlog::get("debug")->debug(">>>>>>>>TCP sending : {}", inputstr);
    bytesWritten += send(clientSd, (char *)&msg, strlen(msg), 0);
   spdlog::get("debug")->debug("Awaiting server response...");
    memset(&msg, 0, sizeof(char)*3500); // clear the buffer
    bytesRead += recv(clientSd, (char *)&msg, sizeof(msg), 0);
    if (bytesRead > 0 && msg[0] != '\0' && outputstr !=NULL)
    {
       spdlog::get("debug")->debug("Server: {}", std::string(msg));
        *outputstr = std::string(msg);
        
    }

   spdlog::get("debug")->debug("Bytes written: {} Bytes read: {}", bytesWritten, bytesRead);
    if(bytesRead == 0)
    {
        close(clientSd);
        return 0;
    }
    if (bytesRead == -1) { 
    switch (errno) {
        case EAGAIN:
          perror("Failed to read from socket: code = EAGAIN");
          close(clientSd);
          break;
        default:
          perror("Failed to read from socket");
          close(clientSd);
          break;
    }
    return -2;
}
    close(clientSd);
    return 0;
}

这是堆栈跟踪:

--- command='' signal=11 date='29/08/2024 16:45:10' ---
    ./backend(+0x115207) [0x561998dcb207]
    /lib/x86_64-linux-gnu/libc.so.6(+0x3ef10) [0x7f4530a03f10]
    ./backend(_ZN7backend8software19send_tcp_remote_cmdENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPS6_s+0x10b) [0x561998fa2abb]
    ./backend(_ZN7backend8software20get_disk_utilizationENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+0x125) [0x561998fa5be5]
    ./backend(+0x18053e) [0x561998e3653e]
    ./backend(_ZN7httplib6Server7routingERNS_7RequestERNS_8ResponseERNS_6StreamE+0x580) [0x561998e171d0]
    ./backend(_ZN7httplib6Server15process_requestERNS_6StreamEbRbRKSt8functionIFvRNS_7RequestEEE+0xac2) [0x561998e18762]
    ./backend(_ZN7httplib9SSLServer24process_and_close_socketEi+0x49b) [0x561998e191db]
    ./backend(_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJN7httplib10ThreadPool6workerEEEEEE6_M_runEv+0x150) [0x561998ebba10]
    /usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0xe067f) [0x7f453145767f]
    /lib/x86_64-linux-gnu/libpthread.so.0(+0x76db) [0x7f453262c6db]
    /lib/x86_64-linux-gnu/libc.so.6(clone+0x3f) [0x7f4530ae661f]

我认为这可能是由不正确的 memset() 引起的,但事实并非如此。

c++ linux sockets segmentation-fault
1个回答
0
投票

那么,如果

inputstr
的长度等于或大于神奇的3500(
msg
的大小)怎么办?

strcpy(msg, inputstr.c_str());

您写入随机内存(本地堆栈,这可能很长一段时间不可见)。

如果接收到的数据恰好等于神奇的 3500 (

sizeof(msg)
) 怎么办?

bytesRead += recv(clientSd, (char *)&msg, sizeof(msg), 0);

\0
末尾的哨兵
msg
被消灭。因此,在复制到
std::string
函数
clone
时会出现段错误。

© www.soinside.com 2019 - 2024. All rights reserved.