Я создал функцию, которая читает из файла, и заполняет структуру данных на основе этого файла. Функция работает очень хорошо, поэтому я решил создать 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);
Что представляет собой отображение времени выполнения следующего вида:
Это хорошо, так LPCWSTR File
теперь содержит значение из структуры LPOPENFILENAME
, но когда инициализируется wstring
значением File
, обе переменные, похоже, выходят за пределы диапазона или вытаскивают из местоположения указателя, которое больше не точнее и появляются их значения быть чем-то вроде:
Цель состоит в том, чтобы сохранить имя файла в строке, чтобы я мог (подобно PHP) сбежать с символами "\"
чтобы вставить в мою функцию. Как таковой:
C:\Users\InfinityMachine\Documents\Test.obj
→ C:\\Users\\InfinityMachine\\Documents\\Test.obj
В котором я:
while (Fileformatting.find(L"\\") != wstring::npos){
Fileformatting.replace(Fileformatting.find(L"\\"), 2, L"\\\\");
}
Как я могу получить правильное значение LPCWSTR File
в wstring Fileformatting
?
Вероятно, вы инициализировали lpstrFile
переменной, которая является локальной функцией FileOpenOBJ
, и когда эта функция вернется, вы получите неопределенное поведение при попытке ее использования. Кажется, он работает впервые, потому что стек еще не реализован, но это изменяется, когда вы вызываете MessageBox
.
Перемещение инициализации wstring
замаскировало бы проблему, но не исправляло бы ее, вы все еще полагаетесь на неопределенное поведение. Исправление будет состоять в том, чтобы структура содержала указатель, который не выходит за рамки.
LPCWSTR File = FileOpenOBJ(hWnd, hInst).lpstrFile;
решить эту проблему, скопировав значение во внешнюю переменную до того, как функция выйдет из области видимости?
OPENFILE
возвращаемая функцией, все еще находится в области видимости, но эта структура содержит указатель, который вы должны установить самостоятельно. Вы не показали тело функции, где она будет установлена, но держу пари, я прав, что это локальный буфер. Этот буфер выйдет из области видимости, как только функция вернется, и вам просто повезло, что MessageBox
сработал.
В дополнение к тому, что другие говорили об оборванных указателях и т.д., Для такой ситуации вам лучше просто иметь 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()
.
if (GetOpenFileNameW(&OpenFilenameDesc)){ wstring File(OpenFilenameDesc.lpstrFile); return File; }