Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Что делать со вторым параметром GetCurrentDirectory(int, LPTSZTR ZdesKosak)  (Прочитано 15288 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
Mike_I
Участник

ru
Offline Offline
Пол: Мужской
Mike


« : 07-06-2006 05:37 » 

Привет народ.
Исользую функцию GetCurrentDirectory() в VC.net
Первый ее параметр размер буфера, второй сам указатель на буфер, в буфере
после выполнения находится путь к рабочей директории приложения.
Вроде все работает путь возвращается правильно, но после его получения
с текстовым буфером ничего нельзя сделать, ни записать в него ни даже удалить!!!

Код:
try
{
  CString strPath;

  strPath = "";// Здесь все инициализируется нормально
  dwExecutionResult = GetCurrentDirectory( 55, strPath.GetBuffer() );
 
  strPath = "123";// Здесь выскакивает ошибка
}// Если закоментить предыдущую строку то ошибка выскочит когда придем сюда
catch(......
« Последнее редактирование: 07-06-2006 08:39 от Джон » Записан

Nothing fails like success.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 07-06-2006 08:46 » 

Mike_I,  лучше конечно понимать, что делаешь. Ты передаёшь в ф-ю пустой буфер, а говоришь, что он у тебя размером 55. Ф-ции по барабану - ты отвечаешь за буфер. Практически она пишет по указателю, который ты ей передал данные. Ессно с переполнением буфера. Вот пошёл ты скажем за пивом, даёшь продавцу рюмку и говоришь: "Налейте мне десять литров." Что получится? Ага

Ты должен буфер сначала подготовить, а потом передать указатель на него в ф-ю GetCurrentDirectory. Откуда у тебя это магическое число 55? А если длинна пути будет 56, или 80, или 100? Поэтому надо передавать буфер с запасом. В таких случаях лучше  пользоваться константами, в данном случае
MAX_PATH, например так:
Код:
	char chCurDir[MAX_PATH];
memset(chCurDir,0,MAX_PATH);
::GetCurrentDirectory(MAX_PATH,chCurDir);
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Anchorite
Гость
« Ответ #2 : 07-06-2006 15:20 » 

Должно быть так:
   
Код:
try {
    DWORD dwBufferLength = ::GetCurrentDirectory(0, NULL);
    CString strPath;

    dwExecutionResult = GetCurrentDirectory(dwBufferLength, strPath.GetBuffer(dwBufferLength));
    strPath.ReleaseBuffer();
}
catch(......

Записан
Mike_I
Участник

ru
Offline Offline
Пол: Мужской
Mike


« Ответ #3 : 29-06-2006 09:57 » 

Джон:
Но за буфер, я думаю, случае должны отвечать функции класса CString, на то он и есть. К тому же даже если буфер неверен к тому что переменная закрывается для использования, это отношения не имеет. По идее должна просто стерется часть нужной инфы. Это все-равно что продавец тебе налил 3 литра пива в литровую банку, 2 соответственно вылилось, но фишка в том что банка при этом прилипла к прилавку и ее не унести, с недостаточным ее объемом это не связано.
Записан

Nothing fails like success.
Mike_I
Участник

ru
Offline Offline
Пол: Мужской
Mike


« Ответ #4 : 29-06-2006 10:23 » 

Anchorite:
 Если сделать как ты говоришь то ошибка выскакивает на строке
  strPath.ReleaseBuffer();
Записан

Nothing fails like success.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 29-06-2006 12:22 » 

Mike_I, По умолчанию в объекте выделена память под буфер 16 байт. Тем более ты иницилизируеш так
Код:
strPath = "";
В функцию ты отдаеш указатель на данный буфер, который находится в объекте. WinAPI функция не знает, и знать не хочет, что ты ей подсовываеш. Она думает что ты даеш указатель на  массив символов размером 55 байт. Естественно честно пишет в эти 55 байт. И естествено полностью уничтожает все данные самого экземпляра объекта строки и прилежаших с ней переменных. Классический пример ошибки переполнения буффера.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #6 : 29-06-2006 12:55 » 

Mike_I, ты думаешь не правильно (в данном случае), поэтому ещё раз призову тебя сначала разобраться с материей, прежде чем делать выводы (ошибочные). Ага

Дело в том, что в ф-ю GetCurrentDirectory НЕ передаётся объект CString. Если бы это было так, тогда конечно не надо было бы передавать размер - объект сам позаботился бы о размере своего буфера. А так передаётся указатель типа char, и как же, скажи пожалуйста, через него ф-я GetCurrentDirectory должна управлять объектом CString? Может придумаешь? Ага

А посему повторю ещё раз (в последний - если не поймёшь, я уж и не знаю) - это не проблема объекта CString, а ф-ции GetCurrentDirectory. Ты сам должен позаботиться о размере буфера, как впрочем при работе практически с любой ф-ей API, запрашивающей буфер для ввода данных.
В примере Anchorite указание объекту создать сначала буфер необходимого размера даётся с помощью параметра ф-ции GetBuffer, который он запросил у GetCurrentDirectory, вызвав её с параметром NULL.

А с буфером всё происходит так как я объяснил, а не так как тебе хочется. Ты создаёшь объект strPath и обнуляешь его strPath = ""; Вызови GetLength и убедись, что длинна равна нулю.
Потом ты передаёшь указатель на кусок памяти размером 0 (заключающий нуль я не считаю) в ф-ю и говоришь напиши мне туда 55 байт. Даже если запрашиваемый путь всего 3 символа "c:\" - уже происходит ошибка всех новичков и дилетантов (залог успешной работы всех хакеров) - переполнение буфера. В дебаге ты можешь это и не заметить. Всё! 55 литров пива вылиты в банку с нулевым объёмом. Твоя память в сортире, какие могут быть последствия не скажет тебе никто. Даже ГБ и БГ.
Тебе повезло, что вылетает в след строчке - ошибку сразу видно. У меня подобная ошибка приводила к тому, что сбой происходил в совершенно другом месте, при совершенно другой операции. И найти подобные ошибки в большом проекте ой как тяжело. Так что учи мат. часть.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #7 : 29-06-2006 13:12 » 

зы По причине жуткой нехватки времени - отвечал почти целый день. За это время пришли ещё сообщения.

Anchorite показал направление в котором надо работать. Ведь весь твой код мы не видим. А так ещё надо учитывать размерность символа - например в UNICODE он равен не одному, а двум байтам. CString свободно обходтся с подобными вещами и возвращает число символов, а не байт. Поэтому правильно использовать так - dwBufferLength*sizof(TCHAR)
Это раз. Два - размер буфера в GetBuffer(dwBufferLength) не учитывает заключительный ноль. И если GetCurrentDirectory прописывает его сама - получаем опять переполнение буфера.
И наконец третье - перед тем как вызывать Release ты должен убедится, что никто не работает с буфером.
« Последнее редактирование: 29-06-2006 13:14 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Mike_I
Участник

ru
Offline Offline
Пол: Мужской
Mike


« Ответ #8 : 29-06-2006 13:46 » 

Джон:
 А как мне тогда инициализировать strPath если буфер должен быть допустим 100 символов писать что-то типа:
 strPath = "123456789012345678901234567890...и так еще 70 раз";
Записан

Nothing fails like success.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #9 : 29-06-2006 13:53 » 

Если так хочется работать с API и MFC:
Код:
CString GetCurDir()
{
CString stOut=_T("");
DWORD dwLen = ::GetCurrentDirectory(0,NULL);
TCHAR *pszCurDir = new TCHAR[dwLen+1];
memset(pszCurDir,0,dwLen*sizeof(TCHAR));
::GetCurrentDirectory(dwLen,pszCurDir);
stOut = CString(pszCurDir);
delete [] pszCurDir;
return stOut;
}


зы ф-я работает с UNICODE и с ANSI (второе не проверял - у меня ща UNICODE проект)
« Последнее редактирование: 29-06-2006 14:00 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #10 : 29-06-2006 13:55 » 

Джон:
 А как мне тогда инициализировать strPath если буфер должен быть допустим 100 символов писать что-то типа:
 strPath = "123456789012345678901234567890...и так еще 70 раз";


Mike_I, ну ну это уже национаглость - ты мои посты вобще не читаешь?
Для подобных случаев есть константы - длинна пути ограничена в винде - я думал, что это общеизвестный факт.

В таких случаях лучше  пользоваться константами, в данном случае
MAX_PATH, например так:
Код:
	char chCurDir[MAX_PATH];
memset(chCurDir,0,MAX_PATH);
::GetCurrentDirectory(MAX_PATH,chCurDir);

Использование константы особенно рекомендовано при компиляции на разных платформах кажется под 9х длинна равна 256, а под виндой 2 КБ (ща точно не помню)
« Последнее редактирование: 29-06-2006 13:57 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines