솔루션/해결 방법 : 실제로
, QByteArray
의 qDebug()
출력이 '\0'
문자에서 잘립니다. 이것은 QByteArray와 관련이 없습니다. qDebug()를 사용하여 '\ 0'문자를 출력 할 수도 없다. 설명은 아래를 참조하십시오.
QByteArray buffer;
buffer.append("hello");
buffer.append('\0');
buffer.append("world");
qDebug() << "GNSS msg (" << buffer.size() << "): " << buffer;
출력 : 심지어 어떤 다음 인수는 무시됩니다
GNSS msg (11): "hello
:
qDebug() << "hello" << '\0' << "world";
출력 :
hello
당신은 대체하여이 "문제"를 해결할 수 있습니다 바이트의 특수 문자 를 디버깅하기 전에 배열 :
QByteArray dbg = buffer; // create a copy to not alter the buffer itself
dbg.replace('\\', "\\\\"); // escape the backslash itself
dbg.replace('\0', "\\0"); // get rid of 0 characters
dbg.replace('"', "\\\""); // more special characters as you like
qDebug() << "GNSS msg (" << buffer.size() << "): " << dbg; // not dbg.size()!
출력 :
GNSS msg (11): "hello\0world"
왜 이런 일이? qDebug()를 사용하여 '\0'
을 출력 할 수없는 이유는 무엇입니까?
무엇이 qDebug()
인지 알아 보려면 Qt 내부 코드를 살펴 보겠습니다. 다음 코드 단편은 Qt 4.8.0 소스 코드에서 발췌 한 것입니다.
당신이 qDebug() << buffer
을 수행 할 때이 메소드가 호출된다
inline QDebug &operator<<(const QByteArray & t) {
stream->ts << '\"' << t << '\"'; return maybeSpace();
}
stream->ts
은 위의 QString
에 QByteArray
변환 형 QTextStream
,이다 :
QTextStream &QTextStream::operator<<(const QByteArray &array)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
// Here, Qt constructs a QString from the binary data. Until now,
// the '\0' and following data is still captured.
d->putString(QString::fromAscii(array.constData(), array.length()));
return *this;
}
당신이 볼 수 있듯이, d->putString(QString)
(d
의 형식은 텍스트 스트림의 내부 전용 클래스입니다.)를 호출합니다.상수 너비 필드에 대해 일부 패딩을 수행 한 후 나는 putString(QString)
의 코드를 생략하고 직접 다음과 같이 정의된다 d->write(QString)
로 이동 : 당신이 볼 수 있듯이
inline void QTextStreamPrivate::write(const QString &data)
{
if (string) {
string->append(data);
} else {
writeBuffer += data;
if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE)
flushWriteBuffer();
}
}
는 QTextStreamPrivate
는 버퍼를 가지고있다. 이 버퍼의 유형은 QString
입니다. 최종적으로 버퍼가 터미널에 인쇄되면 어떻게 될까요? 이를 위해 qDebug()
문이 끝나고 버퍼가 메시지 처리기로 전달 될 때 어떤 일이 발생하는지 알아야합니다. 기본적으로 메시지 처리기는 터미널에서 버퍼를 인쇄합니다. 그래서 여기
inline ~QDebug() {
if (!--stream->ref) {
if(stream->message_output) {
QT_TRY {
qt_message_output(stream->type, stream->buffer.toLocal8Bit().data());
} QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ }
}
delete stream;
}
}
을 비 바이너리 안전 부분이 다음과 같이 정의된다 QDebug
클래스의 소멸자에서 일어나고있다. Qt는 텍스트 버퍼를 "로컬 8 비트"바이너리 표현으로 변환합니다 (지금까지 AFAIK는 우리가 디버깅 할 바이너리 데이터를 가지고 있어야합니다).
그러나 이진 데이터 길이가 추가 지정되지 않은 메시지 처리기에 전달합니다. 아시다시피, C 문자열의 길이를 알아내는 것은 불가능합니다. '\0'
문자도 포함 할 수 있어야합니다. (위의 코드에서 QString::fromAscii()
이 이진 안전을 위해 추가 길이 매개 변수가 필요한 이유입니다.) 문자를 처리하려는 경우 자체 메시지 처리기를 작성해도 문제가 해결되지 않습니다. 길이를 알아라. 슬프지만 사실이야.
"문제"라는 단어를 인용하지 않겠지 만 실제로 버그가있는 것 같습니다 (qDebug가 정상적으로 추가 한 문자열 뒤에 누락 된 "닫기"로 입증 됨). –
@fish 나는 또한 데이터를 " \ 0'' 좋은 아니에요. 다른 측면에서, 나는 qDebug 출력 (적어도 QString 및 QByteArray)에 대한 텍스트 데이터를 만든 것 같아요. 하나는 QByteArray의 경우,이 * 안된다고 주장 할 수 있습니다 * 그러나 Qt가 어떻게 바이너리 데이터를 디버깅하길 원하는지 모르겠다 고 주장 할 수 있습니다 .0 문자를 출력해도 작동하지만 하나도 읽을 수 없습니다 (qDebug()의 목적입니다). 아마도 .toHex() 어떤 경우에는 바이너리 데이터를위한 더 나은 솔루션입니다. 그래서 Qt는 데이터를 출력하는 방법을 여러분에게 맡깁니다. – leemes
그렇지만 이것이 올바른 행동이라고 주장 할 수 있습니다. 그것은 의도하지 않았고 그렇지 않은 경우 추가 누락 ". –