C ++ / Qt memcpy与QSharedMemory崩溃

时间:2017-04-13 11:39:38

标签: c++ qt crash memcpy qsharedmemory

我有一个简单的函数,它使用Qt(5.5.1)QSharedMemory类将字符串(uri链接或文件路径)发送到已经运行的应用程序实例。

它似乎在大多数时候都能正常工作,但我从用户那里抓到了一个崩溃日志,它在memcpy上崩溃了。该函数如下所示:

void WindowsApp::SendData( char* uri )
{
    int size = 1024;
    if (!m_SharedMemory.create(size)) {
        qDebug() << "Unable to create shared memory segment." << m_SharedMemory.error();
        return;
    }
    m_SharedMemory.lock();
    char *to = (char*)m_SharedMemory.data();
    const char *from = uri;
    memcpy(to, from, qMin(m_SharedMemory.size(), size));
    m_SharedMemory.unlock();
    QThread::sleep(10);
}

m_SharedMemory是该类的QSharedMemory类型静态成员。

从日志中,我看到我尝试发送的字符串是一个没有特殊字符的简单文件路径,并且不会太长,只有150个字符。

有什么不对,但是我无法用类似的参数重现它?

1 个答案:

答案 0 :(得分:1)

代码具有未定义的行为,因为您正在读取源字符串的末尾:即使源字符串是例如,您也总是读取1024个字节。 5个字节长。正如您所指出的,UB并不是崩溃的保证。通常它会在重要演示期间崩溃。如果字符串太长而无法放入内存段,您也无法确保字符串将被终止,因此如果接收器尝试将字符串视为零终止,则接收器可能会崩溃

这些问题可能是由于缺乏设计。内存段的内容意味着发送方和接收方之间的合同。两者都必须达成一致意见。让我们来定义合同:

  1. 共享内存段的内容是以空字符结尾的C字符串。

    这是一种所谓的不变性:无论如何,它总是如此。这使读者能够安全地使用C字符串API,而无需先检查是否存在空终止。

  2. 太长的uri被空字符串替换。

    这是作者的后置条件:它意味着写作将在内存中放置一个完整的URI,或者是一个空字符串。

  3. 以下是解决问题的方法:

    =countif($b:$e, b2)=1