【问题标题】:ask : memmove() and memcpy() on QT (c++)问:QT (c++) 上的 memmove() 和 memcpy()
【发布时间】:2012-04-13 21:02:09
【问题描述】:

简单的问题,我在使用 memmove() 和 memcpy() 时遇到问题。我真的不明白我的代码有什么问题。顺便说一句,我使用 QT。

HANDLE hFile;
HANDLE hMapFile;
HANDLE hMapView;

hFile = CreateFileW((const wchar_t*) objPath.constData(), GENERIC_READ , 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE){

    hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hMapFile != INVALID_HANDLE_VALUE){

        hMapView = MapViewOfFile(hMapFile, GENERIC_READ, 0, 0,0);
        if (hMapView != INVALID_HANDLE_VALUE){
            uint DefineWord;
            memmove((void *) &DefineWord, hMapView,2); // <- always error right here
            qDebug()<<DefineWord;
        }
    }
}

【问题讨论】:

  • 如果您更明确地说明您的要求,将会很有帮助。你有一条评论,埋在你的源代码中,说“总是在这里出错”。请准确告诉我们错误是什么(是否有错误消息?),并在您的问题中提供该信息,而不仅仅是在您的源代码中。谢谢。
  • 特别是,您在编译代码或运行代码时是否遇到错误?
  • 当我调试时,有一条消息“segmentation fault”SIGSEGV。
  • 你有#include &lt;string.h&gt;吗?没有它,编译器就看不到memmove 的声明,也不一定能诊断出用错误类型的参数调用它(正如 Zan Lynx 所说,hMapView 不是指针)。但是应该有一个编译时警告;有吗?
  • 当然我有#include ,我也将声明更改为LPVOID hMapView。总是出现相同的错误消息。

标签: c++ qt winapi memory


【解决方案1】:

hMapView 不是指针。 memmove 需要两个指针。通过正确声明 hMapView 来解决此问题。应该是LPVOID

【讨论】:

  • 我还将声明更改为 LPVOID hMapView。总是出现相同的错误消息。 “分段错误” SIGSEGV。
【解决方案2】:

MapViewOfFile 返回一个指针,或者在出错时返回NULL (0),而不是INVALID_HANDLE_VALUE (-1)。

编辑:您的代码还有很多其他问题:

  • QString::constData() 返回QChar*,而不是wchar_t*,你必须使用QString::utf16()
  • 如果CreateFileMappingW 失败,则返回NULL,而不是INVALID_HANDLE_VALUE
  • MapViewOfFile 访问参数是FILE_MAP_READ,而不是GENERIC_READ
  • uint 通常大于 2 个字节,因此如果只读取 2 个字节,则应在 memmove 之前将变量初始化为 0。

这是一个应该可以工作的最小代码(仅在 wineg++/wine 上测试过):

#include <windows.h>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>

int main(int argc, char const *argv[])
{
    if (argc < 2) {
        QTextStream(stdout) << "Usage :" << argv[0] << " filename" << endl;
        return 1;
    }

    QString objPath(argv[1]);
    // Qt source uses C-Style cast from utf16() to (wchar_t*),
    // so it should be safe
    HANDLE hFile = CreateFileW((const wchar_t *) objPath.utf16(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        qDebug() << qt_error_string(); 
    } else {
        HANDLE hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (!hMapFile) {
            qDebug() << qt_error_string(); 
        } else {
            void *pMapView = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
            if (!pMapView) {
                qDebug() << qt_error_string();
            } else {
                uint DefineWord = 0;
                memmove((void *) &DefineWord, pMapView, 2);
                qDebug() << DefineWord;
            }
            CloseHandle(hMapFile);
        }
        CloseHandle(hFile);
    }
    return 0;
}

PS:QString qt_error_string(int errorCode = -1) 是一个明显未记录的 Qt 函数,它返回最后一个错误的错误字符串(来自 GetLastError()errno 返回的错误代码)。

如果您使用 Qt,您可以使用 QFile::map() 将文件映射到内存。
要执行初始代码应该执行的操作,您只需在找到的代码示例中添加 2 行(加上错误检查):

QFile file("foo"); 
if(!file.open(QFile::ReadOnly)) {
   qDebug() << file.errorString();
} else {
    uchar *memory = file.map(0, file.size()); 
    if (!memory) {
        qDebug() << file.errorString();
    } else {            
        uint DefineWord = 0;
        memmove(&DefineWord, memory, 2);

        file.unmap(); 
    }
} 

【讨论】:

  • 我不明白如何使用 QFile::map() 映射文件。但是,我有一些示例代码。 QFile 文件(“foo”); file.open(QFile::ReadOnly); uchar *memory = file.map(0, file.size()); if (memory) { // 享受数据的乐趣 file.unmap(); }
【解决方案3】:

顺便说一句,我使用 QT。

您在示例中并没有真正使用它。 Qt 有 QFile::map 方法,可以(并且在我看来应该)用来代替特定于平台的 MapViewOfFile。

【讨论】:

  • 这真的是问题的答案,还是应该是评论?
  • @KeithThompson:如果您不喜欢我的回答,请自己写。使用 3-deep level if 而不是单行代码会适得其反。
  • 您可能会提供很好的建议(我对MapViewOfFileQFile::Map 不够熟悉,无法确定这一点)。我只是不相信这是对 OP 所问问题的直接回答,这似乎类似于“为什么我在这段代码中遇到错误?”如果您能够诊断出问题提出更好的解决方案,那么您将得到一个很好的答案。
猜你喜欢
  • 1970-01-01
  • 2011-05-23
  • 2013-08-13
  • 2010-11-15
  • 2016-06-09
  • 2011-04-17
  • 1970-01-01
  • 2011-07-21
相关资源
最近更新 更多