вылет в strstr в релизной версии
От: Аноним  
Дата: 06.02.08 09:53
Оценка:
Здравствуйте мне PM поставил задачу:
Сделать так что бы наш проект запускался напрямую со стартима.
Покопавшись в проблеме я увидел что при запуске со стартима, текущая директория указывалась куда попало, сделал так:

.................................................
          TCHAR  path[MAX_PATH];
          GetModuleFileName(NULL,  path, MAX_PATH);
      if(strstr(path,"starbase")){
          PathRemoveFileSpec(path);
          PathAddBackslash(path);
         ::SetCurrentDirectory(path);
}
.......................................................

Но при запуске из стартима, происходит падение в функции strstr, причем, только в релизной версии.
Re: вылет в strstr в релизной версии
От: Cruser Украина  
Дата: 06.02.08 10:26
Оценка:
А>
А>.................................................
А>          TCHAR  path[MAX_PATH];
А>          GetModuleFileName(NULL,  path, MAX_PATH);
А>      if(strstr(path,"starbase")){
А>          PathRemoveFileSpec(path);
А>          PathAddBackslash(path);
А>         ::SetCurrentDirectory(path);
А>}
А>.......................................................

А>

А>Но при запуске из стартима, происходит падение в функции strstr, причем, только в релизной версии.

          TCHAR  path[MAX_PATH];
          if(GetModuleFileName(NULL,  path, MAX_PATH) > 0) {
            if(strstr(path,"starbase")){
          ...


Если GetModuleFileName возвращает 0, смотри GetLastError()
... << RSDN@Home 1.2.0 alpha rev. 789>>
Re: вылет в strstr в релизной версии
От: Кодт Россия  
Дата: 06.02.08 11:11
Оценка: 6 (1)
Здравствуйте, <Аноним>, Вы писали:

А>
А>TCHAR  path[MAX_PATH];
А>GetModuleFileName(NULL,  path, MAX_PATH);
А>if(strstr(path,"starbase"))
    .....
А>


Во-первых, либо TCHAR, GetModuleFileName, _tcsstr(path, _T("starbase")), либо char, GetModuleFileNameA, strstr(path, "starbase").
Но это так, мелочи.

Причина же в том, что — по видимому, в релизе из-под стартима длина имени файла оказалась больше, чем MAX_PATH.
Поэтому GetModuleFileName() не дописал туда концевой ноль

lpFilename
A pointer to a buffer that receives the fully-qualified path of the module. If the length of the path exceeds the size that the nSize parameter specifies, the function succeeds, and the string is truncated to nSize characters and cannot be null terminated.

После чего strstr уехал искать конец строки вверх по стеку...

Чтобы проверить это, нужно посмотреть на GetLastError() == ERROR_INSUFFICIENT_BUFFER.
А чтобы пресечь проблемы — достаточно после GetModuleFileName() написать path[MAX_PATH-1]=0.

Хотя по-человечески было бы так
// ATL или MFC CString; при желании можно поплясать вокруг STL и возвращать basic_string<TCHAR>
CString GetModuleFileName(HMODULE hmodule)
{
    DWORD len = ::GetModuleFileName(hmodule,NULL,0);
    CString path;
    ::GetModuleFileName(hmodule, path.GetBuffer(len+1), len+1);
    path.ReleaseBuffer();
    return path;
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: вылет в strstr в релизной версии
От: Аноним  
Дата: 06.02.08 12:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, <Аноним>, Вы писали:


А>>
А>>TCHAR  path[MAX_PATH];
А>>GetModuleFileName(NULL,  path, MAX_PATH);
А>>if(strstr(path,"starbase"))
К>    .....
А>>


К>Во-первых, либо TCHAR, GetModuleFileName, _tcsstr(path, _T("starbase")), либо char, GetModuleFileNameA, strstr(path, "starbase").

К>Но это так, мелочи.

К>Причина же в том, что — по видимому, в релизе из-под стартима длина имени файла оказалась больше, чем MAX_PATH.

К>Поэтому GetModuleFileName() не дописал туда концевой ноль
К>

К>lpFilename
К>A pointer to a buffer that receives the fully-qualified path of the module. If the length of the path exceeds the size that the nSize parameter specifies, the function succeeds, and the string is truncated to nSize characters and cannot be null terminated.

К>После чего strstr уехал искать конец строки вверх по стеку...

К>Чтобы проверить это, нужно посмотреть на GetLastError() == ERROR_INSUFFICIENT_BUFFER.

К>А чтобы пресечь проблемы — достаточно после GetModuleFileName() написать path[MAX_PATH-1]=0.

К>Хотя по-человечески было бы так

К>
К>// ATL или MFC CString; при желании можно поплясать вокруг STL и возвращать basic_string<TCHAR>
К>CString GetModuleFileName(HMODULE hmodule)
К>{
К>    DWORD len = ::GetModuleFileName(hmodule,NULL,0);
К>    CString path;
К>    ::GetModuleFileName(hmodule, path.GetBuffer(len+1), len+1);
К>    path.ReleaseBuffer();
К>    return path;
К>}
К>


Сделал так:

  GetModuleFileName(NULL,  path, MAX_PATH );
  path[MAX_PATH-1]=0;
  CString sPath(path);
  ::MessageBox(NULL, sPath.GetBuffer(),"info",MB_OK);
     int pos=sPath.Find("starbase");  //При запуске из стартима вот здесь падает
       if(pos>0 )
       {

Просто часть пути из стартима возвращается заглавными буквами, но все ровно не могу понять, почему падает и только в релизе. Сделал так заработало:

CString sPath(path);
sPath=utils::to_lower(sPath);
.........................................................
Re: вылет в strstr в релизной версии
От: Stormblast http://www.myspace.com/stormblastblack
Дата: 08.02.08 08:39
Оценка:
Здравствуйте, Аноним, Вы писали:
А>
А>.................................................
А>          TCHAR  path[MAX_PATH];
А>          GetModuleFileName(NULL,  path, MAX_PATH);
А>      if(strstr(path,"starbase")){
А>          PathRemoveFileSpec(path);
А>          PathAddBackslash(path);
А>         ::SetCurrentDirectory(path);
А>}
А>.......................................................

А>


"starbase" — категорически против такого кода, одни пишет "starbase" другой "StarBase" третий "STARTBASE" а четвертый пишет всегда с ошибками "statbase" ну сколько уже говорить можно ... такие вещи нужно выносить в константы и лучше типизированные ... типа class ConstNameSpace::startBase или т.п.

все эти сишные strstr и т.д. не безопасны, лучше используй stl string find
Re[3]: вылет в strstr в релизной версии
От: Кодт Россия  
Дата: 08.02.08 14:44
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Сделал так:


А>
А>  GetModuleFileName(NULL,  path, MAX_PATH );
А>  path[MAX_PATH-1]=0;
А>  CString sPath(path);
А>  ::MessageBox(NULL, sPath.GetBuffer(),"info",MB_OK);
А>     int pos=sPath.Find("starbase");  //При запуске из стартима вот здесь падает
А>       if(pos>0 )
А>       {
А>

Ты хочешь сказать, что CString::Find падает?! Вау.
Кстати говоря, sPath.GetBuffer() — это лишнее. MessageBox'у нужен LPCTSTR, а не LPTSTR.

А не наведённая ли это ошибка, кстати говоря?
Например, ты где-то умудрился расстрелять память, в которой лежит starbase. Например, элементарно затёр концевой ноль:
void killemall()
{
    char* victim = "starbase"; // или любым другим способом прицелиться на эту строку
    victim[strlen(victim)] = 123;
}

Поскольку компилятор вправе
— размещать строковые литералы как в сегменте констант, так и в сегменте данных
— размещать каждый литерал в отдельном массиве или совмещать одинаковые литералы
то собственно запись в литерал может пройти безболезненно, зато потом узнаешь много новых слов.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: вылет в strstr в релизной версии
От: lifrsdn  
Дата: 08.02.08 14:59
Оценка:
Здравствуйте, Кодт, Вы писали:

А>>
А>>  GetModuleFileName(NULL,  path, MAX_PATH );
А>>  path[MAX_PATH-1]=0;
А>>  CString sPath(path);
А>>  ::MessageBox(NULL, sPath.GetBuffer(),"info",MB_OK);
А>>     int pos=sPath.Find("starbase");  //При запуске из стартима вот здесь падает
А>>       if(pos>0 )
А>>       {
А>>

К>Ты хочешь сказать, что CString::Find падает?! Вау.
К>Кстати говоря, sPath.GetBuffer() — это лишнее. MessageBox'у нужен LPCTSTR, а не LPTSTR.

Не только лишнее, но и пропущен sPath.ReleaseBuffer(). Может из-за этого проблемы?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: вылет в strstr в релизной версии
От: Кодт Россия  
Дата: 08.02.08 16:44
Оценка:
Здравствуйте, lifrsdn, Вы писали:

К>>Кстати говоря, sPath.GetBuffer() — это лишнее. MessageBox'у нужен LPCTSTR, а не LPTSTR.

L>Не только лишнее, но и пропущен sPath.ReleaseBuffer(). Может из-за этого проблемы?

Мне казалось, что CString терпимо относится к этому делу. Грубо говоря, GetBuffer обеспечивает монопольное владение строкой (поскольку MFC/ATL практикует COW), а ReleaseBuffer выполняет измерение длины и снова разрешает совместное использование.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[6]: вылет в strstr в релизной версии
От: lifrsdn  
Дата: 08.02.08 16:49
Оценка:
Здравствуйте, Кодт, Вы писали:

К>>>Кстати говоря, sPath.GetBuffer() — это лишнее. MessageBox'у нужен LPCTSTR, а не LPTSTR.

L>>Не только лишнее, но и пропущен sPath.ReleaseBuffer(). Может из-за этого проблемы?

К>Мне казалось, что CString терпимо относится к этому делу. Грубо говоря, GetBuffer обеспечивает монопольное владение строкой (поскольку MFC/ATL практикует COW), а ReleaseBuffer выполняет измерение длины и снова разрешает совместное использование.


Это так, но ReleaseBuffer ещё и устанавливает длину строки. Когда были проблемы, что после неотпущенного буфера, длина строки считалась нулевой, что и приводило к проблемам. Код правда не падал, но как говорится мало ли? Взял — отдай обратно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: вылет в strstr в релизной версии
От: Xander Zerge Россия www.zerge.com
Дата: 08.02.08 19:11
Оценка:
Здравствуйте, Stormblast, Вы писали:

А>>
А>>.................................................
А>>          TCHAR  path[MAX_PATH];
А>>          GetModuleFileName(NULL,  path, MAX_PATH);
А>>      if(strstr(path,"starbase")){
А>>.......................................................

А>>


S>все эти сишные strstr и т.д. не безопасны, лучше используй stl string find


Ну и инициализировать переменные, проверять код возврата из функций на ошибки, ну и не перемешивать строковые типы TCHAR с CHAR: if(_tcsstr(path,_T("starbase")){.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Серёжа Новиков,
программист
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.