Хорошо, я занимаюсь этим уже два дня и не могу найти решение.
Проблема: Я пытаюсь установить фильтр на Диалог выбора файла используя Winapi. я использую GetOpenFileName
Функция для этого. Эта функция использует состав установить параметры, такие как фильтры расширений файлов. Член этой структуры называется lpstrFilter
нужен определенный формат строки. Я устанавливаю эту строку точно так, как указывает Winapi, но по какой-то причине значение этой строки изменяется.
У меня есть это статический константный символ *:
//This contains string "JPG"static const char * extensionFilter = v->trabajo10.C_JMV_SelectFile_FileExtension7.GetString();
//This forms a filter string which applies to OPENFILENAME structure.
string sFilter;
sFilter.append("Format: ");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
sFilter.append("*.");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
const char * filter = sFilter.c_str();
ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
//This opens the file selection dialog
if (GetOpenFileName(&ofn)==TRUE){
...
Диалог выбора файла выглядит ПРАВИЛЬНО, как это:
Пришла шутка, я модифицирую код так:
//This contains string "JPG"static const char * extensionFilter = v->trabajo10.C_JMV_SelectFile_FileExtension7.GetString();
if(1){
//This forms a filter string which applies to OPENFILENAME structure.
string sFilter;
sFilter.append("Format: ");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
sFilter.append("*.");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
const char * filter = sFilter.c_str();
ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
}
//This opens the file selection dialog
if (GetOpenFileName(&ofn)==TRUE){
...
И это результат, ЭТА ПРОБЛЕМА:
Строка фильтра была изменена ???
if(1){
//This forms a filter string which applies to OPENFILENAME structure.
string sFilter;
sFilter.append("Format: ");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
sFilter.append("*.");
sFilter.append(extensionFilter);
sFilter.push_back('\0');
const char * filter = sFilter.c_str();
ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
}
sFilter
Переменная имеет время жизни, которое заканчивается, когда заканчивается блок, в котором она была объявлена. Указатель возвращается sFilter.c_str()
действует до sFilter
модифицируется или уничтожается.
Вы используете этот указатель после того, как он стал недействительным. Это та же проблема, что и у вас вчера, о которой я догадывался в комментариях к вопросу. Вот почему вам нужно показать полный MCVE. Этот вопрос также выглядит дубликатом того, который вы задали неделю назад: Winapi GetOpenFileName Расширение фильтра не работает. Я предлагаю вам потратить некоторое время на то, чтобы убедиться, что вы полностью оценили правильность значения, возвращаемого c_str()
,
Вы должны убедиться, что sFilter
живет до тех пор, пока вы не закончили с указателем. декларировать sFilter
во внешнем блоке, чтобы обеспечить это.
Проблема в том, что у вас есть переменная, которая выпала из области видимости
if(1){
string sFilter;
// ... code
// Right here
const char * filter = sFilter.c_str();
ofn.lpstrFilter = filter;
}
После того, как этот блок заканчивается filter
выходит за рамки, так ofn.lpstrFilter
имеет висячий указатель.
Отвечая на вопрос ProtectedVoid по поводу объявления неиспользуемого объекта: представьте себе std::string
был дорогой объект, и состояние было маловероятным. Вы не хотите, чтобы объект был построен, если условие не выполняется. Но тогда это должно продолжаться за рамками условия. Таким образом, мы используем тот факт, что по умолчанию построен unique_ptr
намного дешевле, чем построенный по умолчанию string
:
std::unique_ptr<std::string> scope_extender;
if( something unlikely ){
//This forms a filter string which applies to OPENFILENAME structure.
std::string* sFilter = new std::string;
scope_extender.reset( sFilter );
sFilter->append("Format: ");
sFilter->append(extensionFilter);
sFilter->push_back('\0');
sFilter->append("*.");
sFilter->append(extensionFilter);
sFilter->push_back('\0');
const char * filter = sFilter->c_str();
ofn.lpstrFilter = filter; //This sets: --> Format: JPG\0*.JPG\0
}
Очевидно, я не хочу подразумевать std::string
достаточно дорого построить, чтобы стоить всех этих хлопот. Но какой-то объект в подобной ситуации может быть. Также был комментарий о том, что если бы было много второстепенных объектов в одном условном выражении. В этом случае вы бы хотели, чтобы служебная структура содержала их все вместе, а unique_ptr условно владеет этой структурой.