Windows API: метаморфоза переменных Unicode

0

Я создал функцию, которая читает из файла, и заполняет структуру данных на основе этого файла. Функция работает очень хорошо, поэтому я решил создать GUI вокруг своей функции. У меня есть функция, которая вызывает графический интерфейс Windows и возвращает структуру LPOPENFILENAME, к которой я LPOPENFILENAME.lpstrFile в LPCWSTR.

Затем я инициализирую wstring для хранения значения LPCWSTR. Здесь, где все становится немного странно.

LPCWSTR File = FileOpenOBJ(hWnd, hInst).lpstrFile;
MessageBox(hWnd, File, L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
wstring Fileformatting(File);

Что представляет собой отображение времени выполнения следующего вида: Изображение 174551

Это хорошо, так LPCWSTR File теперь содержит значение из структуры LPOPENFILENAME, но когда инициализируется wstring значением File, обе переменные, похоже, выходят за пределы диапазона или вытаскивают из местоположения указателя, которое больше не точнее и появляются их значения быть чем-то вроде:

Изображение 174551Изображение 174551

Цель состоит в том, чтобы сохранить имя файла в строке, чтобы я мог (подобно PHP) сбежать с символами "\" чтобы вставить в мою функцию. Как таковой:

C:\Users\InfinityMachine\Documents\Test.objC:\\Users\\InfinityMachine\\Documents\\Test.obj

В котором я:

while (Fileformatting.find(L"\\") != wstring::npos){
    Fileformatting.replace(Fileformatting.find(L"\\"), 2, L"\\\\");
}

Как я могу получить правильное значение LPCWSTR File в wstring Fileformatting?

  • 2
    Похоже, у вас есть свисающий указатель, но трудно сказать с помощью кода, который вы предоставили.
Теги:
string
winapi
unicode
wstring

2 ответа

2
Лучший ответ

Вероятно, вы инициализировали lpstrFile переменной, которая является локальной функцией FileOpenOBJ, и когда эта функция вернется, вы получите неопределенное поведение при попытке ее использования. Кажется, он работает впервые, потому что стек еще не реализован, но это изменяется, когда вы вызываете MessageBox.

Перемещение инициализации wstring замаскировало бы проблему, но не исправляло бы ее, вы все еще полагаетесь на неопределенное поведение. Исправление будет состоять в том, чтобы структура содержала указатель, который не выходит за рамки.

  • 0
    Я боялся этого, но не LPCWSTR File = FileOpenOBJ(hWnd, hInst).lpstrFile; решить эту проблему, скопировав значение во внешнюю переменную до того, как функция выйдет из области видимости?
  • 0
    @InfinityMachine структура OPENFILE возвращаемая функцией, все еще находится в области видимости, но эта структура содержит указатель, который вы должны установить самостоятельно. Вы не показали тело функции, где она будет установлена, но держу пари, я прав, что это локальный буфер. Этот буфер выйдет из области видимости, как только функция вернется, и вам просто повезло, что MessageBox сработал.
Показать ещё 2 комментария
2

В дополнение к тому, что другие говорили об оборванных указателях и т.д., Для такой ситуации вам лучше просто иметь FileOpenOBJ() вернуть wstring вместо копии исходной структуры OPENFILENAME:

wstring FileOpenOBJ(HWND hWnd, HINSTANCE hInst)
{
    WCHAR szFileName[MAX_PATH+1] = {0};

    OPENFILENAME ofn = {0};
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hWnd;
    ofn.hInstance = hInst;
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ...

    GetOpenFileName(&ofn);
    return szFileName;
}

wstring File = FileOpenOBJ(hWnd, hInst);
MessageBoxW(hWnd, File.c_str(), L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);

Если вам нужно вернуть другие значения из OPENFILENAME, вы должны определить свою собственную структуру для хранения того, что вам нужно, например:

struct FileInfo
{
    wstring FullPath;
    wstring FileName;
    wstring Ext;
    int FilterIndex;
    ...
};

FileInfo FileOpenOBJ(HWND hWnd, HINSTANCE hInst)
{
    WCHAR szFileName[MAX_PATH+1] = {0};

    OPENFILENAME ofn = {0};
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hWnd;
    ofn.hInstance = hInst;
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ...

    GetOpenFileName(&ofn);

    FileInfo fi;
    fi.FullPath = szFileName;
    fi.FileName = &szFileName[ofn.nFileOffset];
    if (ofn.nFileExtension != 0)
        fi.Ext = &szFileName[ofn.nFileExtension];
    fi.FilterIndex = ofn.nFilterIndex;
    ...

    return fi;
}

FileInfo fi = FileOpenOBJ(hWnd, hInst);
MessageBoxW(hWnd, fi.FullPath.c_str(), L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);

Не OPENFILENAME прямой доступ к структуре OPENFILENAME. Он должен быть оставлен как частная деталь реализации внутренней логики FileOpenOBJ().

  • 0
    Это было основательно. В итоге я сделал: if (GetOpenFileNameW(&OpenFilenameDesc)){ wstring File(OpenFilenameDesc.lpstrFile); return File; }
  • 0
    Я не могу принять два ответа, но оба ответа точно решили проблему определения объема.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню