【问题标题】:Application crashes while appending data on string在字符串上附加数据时应用程序崩溃
【发布时间】:2014-07-23 20:16:57
【问题描述】:

我有一个跨平台控制台应用程序。它的目的是在两个对等方之间传输数据。有时接收到的数据包不完整,因此我们在完整数据包到达时将数据附加到字符串中。但它会在一段时间后在字符串中附加数据时崩溃。这是后面的tarce -

1 libsystem_c.dylib 0x93b77acf pthread_kill + 101
2 libsystem_c.dylib 0x93bae4f8 abort + 168
3 libc++abi.dylib 0x9698180c abort_message + 151
4 libc++abi.dylib 0x9697f275 default_terminate() + 34
5 libc++abi.dylib 0x9697f2b5 safe_handler_caller(void (*)()) + 13
6 libc++abi.dylib 0x9697f31d std::terminate() + 23
7 libc++abi.dylib 0x96980412 __cxa_throw + 110
8 libstdc++.6.dylib 0x90e23d6c std::__throw_length_error(char const*) + 104
9 libstdc++.6.dylib 0x90e4f3a9 std::string::append(char const*, unsigned long) + 175
10 libConnector.dylib 0x13905228 ConnectionSocket::AdjustPartialData(char const*, int) 
14 libConnector.dylib 0x1383e0b6 ConnectionChannel::ProcessData(int, void const*, int, char*, int) + 7886
15 libConnector.dylib 0x13861ecb ConnectionManager::BaseThreadImpl() + 1185
16 libConnector.dylib 0x13861a23 ConnectionManager::BaseThread(void*) + 17
17 libsystem_c.dylib 0x93b76557 _pthread_start + 344
18 libsystem_c.dylib 0x93b60cee thread_start + 34 

有人可以就这个问题提供任何想法吗?

示例代码:

AdjustPartialData(char* const pData, int dataLen)
{
   if (true == packetIncomplete)
   {
      partialDataBuffer.append(pData, dataLen); // crash occurs in this line
   }

 }

【问题讨论】:

  • 请展示一个小的可重现代码示例。
  • 示例代码已添加到编辑后的帖子中。
  • dataLen 可能有一些错误,可能是在从有符号值到无符号值的转换中,尝试打印它(或在 dbugger 中设置观察点:))
  • 调试器说了什么?
  • cplusplus.com/reference/string/string/append : 如果生成的字符串长度超过 max_size,则会抛出 length_error 异常。

标签: c++ string macos stdstring


【解决方案1】:

如果 partialDataBuffer.size() + dataLen > partialDataBuffer.max_size() then append 抛出 length_error (http://en.cppreference.com/w/cpp/string/basic_string/append)

partialDataBuffer 或 dataLen 太大。

【讨论】:

  • 是的,我考虑过这个选项,但它会导致数据丢失。我也想避免数据丢失。
  • 用更合适的数据结构替换字符串?
  • 或者更好的是处理您的数据。不要只是让它在字符串内部堆积。
  • @Naseef 您仍然没有提供有关为什么要在字符串中累积所有这些数据而不在程序中的某个时刻对数据进行任何操作的信息。你的绳子变得便秘了。通常的解决方案是通过处理那里的数据来清除字符串,以便可以将更多数据添加到字符串中而不会出现问题。
  • @Naseef - 基本上,您需要查看字符串何时“溢出边缘”,当它出现时,创建一个新字符串并让它得到多余的。那么这个新字符串就是将继续获取数据的字符串。冲洗并重复。再一次,比简单的单字符串方法需要更多的逻辑,但希望你明白这一点。使用vector<string> 可以在短时间内实现。
【解决方案2】:

最后我通过丢弃导致溢出的额外数据解决了这个问题。以前我认为这不是可行的解决方案,因为它可能导致数据丢失。但我发现 TCP 流大小不应大于 16 位的 65535。但是在添加以下条件时发现另一个问题 -

if(partialDataBuffer.size() + dataLen >= partialDataBuffer.max_size())
{
 // do not append data
}
else  partialDataBuffer.append(pData, dataLen);

问题出在 Windows 平台上,即使 partialDataBuffer 的大小远小于 partialDataBuffer.max_size(),它也总是崩溃。所以,为了解决这个问题,我做了以下 -

try{
 partialDataBuffer.append(pData, dataLen);
}
catch(...)
{
// got exception, return
}

对我来说效果很好。

N.B:我发布了我的答案,因为它会对面临类似问题的其他人有所帮助。

【讨论】:

  • 但是你会在Windows和其他平台之间产生差异。
  • 我的意思是你的缓冲区对于 Windows 可能比其他平台更短/更大。这可能会导致某些特定于平台的行为。
  • 其实max_size()在不同平台上也返回不同的值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 2014-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多