【问题标题】:different behavior when a std::string variable is global当 std::string 变量是全局变量时的不同行为
【发布时间】:2021-11-06 21:14:38
【问题描述】:

我正在尝试通过套接字发送字符串

while (getline(cin, cmdline)) {
    const char *temp = cmdline.c_str();
    auto n = send(connfd, temp, MAXTEXT, 0) ;
    cout << n << endl;

当 cmdline 为全局变量时,n 为 -1。

错误是“错误地址”

当我将 cmdline 放在 main 的第一行时,套接字工作正常。

奇怪的是,如果我使用调试而不是运行 exe,它也可以正常工作。

gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2

完整的代码可以在这里找到code

【问题讨论】:

  • 请尝试创建minimal reproducible example 向我们展示,否则将很难调试问题。
  • 对了,当send返回-1时,错误是什么?尝试打印errno(例如使用perror("send failed")
  • MAXTEXT -> cmdline.size()?
  • 如果小于4096也是错误的。 send() 无论如何都会尝试读取 4096 字节,因此它将读取未分配的内存。
  • 如前所述,send 函数实际上并不知道它必须发送多少字节,它只使用您提供的大小参数。如果你给它错误的大小,它会很高兴地越界尝试从不属于你的程序的内存中获取数据。这会导致未定义的行为

标签: c++ string sockets


【解决方案1】:

正如 cmets 中所解释的,通过传递 4096,您可以使 send() 超出 cmdline 字符串的范围。您应该使用字符串的大小,或者,如果您仍然希望有限制,请使用大小和限制中的最小值,例如:

int sendSize = std::min<size_t>(cmdline.size(), 4096);
auto n = send(sockfd, cmdline.c_str(), sendSize, 0);

您的服务器端也有问题,因为您的buf 可能没有被\0 终止。要解决这个问题,您可以:

constexpr int MAX_SIZE = 4096;
char buf[MAX_SIZE + 1];   // +1 for terminating '\0' character
// set the first character to '\0' in case we do not receive anything
buf[0] = '\0';
// or in a single line:
// char buf[MAX_SIZE + 1]{ '\0' };

...

n = recv(connfd, buf, MAX_SIZE, 0);
if (n >= 0) {
    buf[n+1] = '\0';
}

【讨论】:

    猜你喜欢
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    相关资源
    最近更新 更多