[英]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.