将QString转换为const char*



为了创建自定义异常类,我需要将QString转换为const char*。这是前面提到的类的主要代码:

// File "Exception.cpp"
const auto MESSAGE_PREFIX = QStringLiteral("Exception ");
Exception::Exception(const char* file, int line, const QString& cause)
: m_Message{MESSAGE_PREFIX + file + ':' + QString::number(line) + ": " + cause}
{
}
const char* Exception::what() const noexcept
{
// QString -> const char*
const auto ba = m_Message.toLocal8Bit();
return ba.constData();
}

因此,转换发生在overriden方法Exception::what中,返回的C字符串指示抛出异常的文件等。

此外,我还定义了一个有助于抛出异常的宏THROW_EXCEPTION_IF()

// File "exception_macros.h"
#include "Exception.h"
#ifdef Q_OS_WINDOWS
#define __FILENAME__ (strrchr(__FILE__, '\') ? strrchr(__FILE__, '\') + 1 : __FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
#define THROW_EXCEPTION_IF(condition, cause)
if (condition) {
auto str = QString{};
QTextStream stream{&str};
stream << cause;
throw Exception{__FILENAME__, __LINE__, str};
}

最后,我用以下代码测试了上面的宏:

void TestException::testMacro()
{
try {
THROW_EXCEPTION_IF(true, "Test")
QVERIFY(false);
}
catch (const std::exception& e) {
QVERIFY(true);
QCOMPARE(QString{e.what()}, QStringLiteral("Exception TestException.cpp:36: Test"));
}
}

问题是:当我在Linux(Qt 5.7.1,GCC 6.3(上运行此测试时,它失败了,并显示以下消息:

失败!:TestException::testMacro((比较值不相同
实际值(QString{e.what((}(:"异常测试Exn\u0000\u0000T\u0000e\u0000s\u0000T\u0000e\u0000x\u0000n\u0000\u0000\u0000"应为(QStringLiteral("Exception TestException.cpp:36:Test"((:";异常测试异常.cpp:36:测试">

在Windows(Qt 5.15(和MSVC 2019上也是一样的问题,但它适用于MinGW 8.1。此外,在Linux上,当我用m_Message.toLatin1()替换m_Message.toLocal8bit()时,测试成功通过。我认为Unicode字符有问题,但我不明白代码中的问题在哪里。非常感谢你的帮助。

您的问题是返回了一个无效的指针:

const auto ba = m_Message.toLocal8Bit(); // here you create a bytearray
return ba.constData();//here you take the pointer to the data of the bytearray
//then you destroy the array, hence the pointer.
//then you return an invalid pointer

你在不同的平台上有不同的行为,因为当指针不再可用时,这是不受保证的。它取决于平台、编译器、编译标志等。

为什么它不起作用

我同意Pablo Yaggi的观点,即您正试图访问销毁的数据,请参阅QByteArray::constData:

[const char *]指针在字节数组未重新分配的情况下保持有效或被销毁。

解决方案

您应该将QByteArray(由toLocal8Bit返回(存储在异常类中(而不是QString(。请注意,您可能希望返回UTF-8编码的字符串(请参阅toUtf8(以支持所有(特殊(字符。如果遇到不支持的字符,则toLocal8BittoLatin1的行为未定义:

如果此字符串包含任何无法在区域设置,返回的字节数组未定义。这些字符可能是被另一个压制或取代。[来源]

相关内容

  • 没有找到相关文章

最新更新