[英]Convert a QString to a 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();
}
因此,转换发生在重写方法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)上运行此测试时,它失败并显示以下消息:
FAIL!: TestException::testMacro() 比较值不一样
实际 (QString{e.what()}):“异常 TestExn\ \ T\ e\ s\ t\ E\ x\ n\ \ \ n\ \ \ ”预期的异常(Q3.测试")): "异常 TestException.cpp:36: 测试"
在 Windows (Qt 5.15) 和 MSVC 2019 上也是同样的问题,但它适用于 MinGW 8.1 。 此外,在Linux上,当我更换m_Message.toLocal8bit()
与m_Message.toLatin1()
测试顺利通过。 我认为 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
)以支持所有(特殊)字符。 如果遇到不受支持的字符,则toLocal8Bit
和toLatin1
的行为未定义:
如果此字符串包含无法在语言环境中编码的任何字符,则返回的字节数组未定义。 这些字符可能会被抑制或替换为另一个字符。 [来源]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.