Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как объяснить исключение при простом присваивании, инициализированной!!! переменной 
:(
    Опции темы
Royan
  Дата 2.7.2004, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Вот мой код:

Код
LPSTR CMyDoc::mMyTrim(LPSTR szStr){
 //MessageBox(NULL, szStr, "", MB_OK);
 
 size_t  nStrLen = 0;
 StringCchLength(szStr, 4096, &nStrLen);
 LPSTR szTemp = new CHAR[nStrLen+1];

 StringCchCopy(szTemp, nStrLen, szStr);
 szTemp = szStr + nStrLen -1;


 //  First trim spaces on the right
 while( (szTemp >= szStr) && (*szTemp == ' ') )
   *szTemp = '\0';//Здесь и возникает ошибка


Переменная szStr приходит из WinMain (это lpCmdStr). На самом деле в том месте где происходит присваивание, *szTemp точно содержит пробел, то есть * не разывеновывает указатель на не проинициализированную область памяти, соответственно и присваивание тоже законно, но по какой-то причине именно в этом месте вылетает исключение


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Nimbus
Дата 4.7.2004, 15:41 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











IMHO, видимо, проблема заключается вот в этой строке:
Цитата
szTemp = szStr + nStrLen -1;

Объясняю, почему:
в строке
Цитата
LPSTR szTemp = new CHAR[nStrLen+1];

была выделена память в области динамического обмена, указатель szTemp содержит теперь АДРЕС начала выделенной области памяти. Затем, в строке
Цитата
szTemp = szStr + nStrLen -1;

этому указателю присваивается адрес хр$н знает какой области памяти, которая, кстати, может быть УЖЕ использована для других целей!
...и затем, в эту хр$н знает какую область памяти, ты записываешь в строке
Цитата
*szTemp = '\0';

символ окончания строки '\0' !!!
По твоему, это корректно???

  Вверх
p0s0l
Дата 4.7.2004, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 2
Всего: 112



Цитата
этому указателю присваивается адрес хр$н знает какой области памяти, которая, кстати, может быть УЖЕ использована для других целей!
А по-моему, у него всё нормально тут: szTemp присваивается адрес последнего ненулевого символа строки szStr...
Только не понятно - зачем там было создавать и копировать строку ?... Задумка не совсем ясна - надо обрезать исходную строку или же обрезать скопированную строку ?
У меня такой код обрезает справа пробелы в szStr нормально, без ошибок:
Код
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR szStr, int)
{
size_t nStrLen = strlen(szStr);
LPSTR szTemp = szStr + nStrLen -1;

//  First trim spaces on the right
while( (szTemp >= szStr) && (*szTemp == ' ') )
  *szTemp-- = '\0';
MessageBox (0, szStr, szStr, 0);
}
(добавил только --, чтобы все пробелы обрезались, а не только один последний)
PS: есть функция StrTrim...




--------------------
С уважением, г-н Посол.
PM   Вверх
Nimbus
Дата 4.7.2004, 23:55 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Признаю, насчет
Цитата
этому указателю присваивается адрес хр$н знает какой области памяти, которая, кстати, может быть УЖЕ использована для других целей!

ПОГОРЯЧИЛСЯ, но постойте, куда же девался post от mr.DUDA (так, кажется, его зовут?) wink.gif
  Вверх
Олег М
Дата 5.7.2004, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 436
Регистрация: 10.6.2004
Где: Москва

Репутация: 7
Всего: 7



[quote]LPSTR CMyDoc::mMyTrim(LPSTR szStr){
//MessageBox(NULL, szStr, "", MB_OK);

size_t nStrLen = 0;
StringCchLength(szStr, 4096, &nStrLen);
LPSTR szTemp = new CHAR[nStrLen+1];

StringCchCopy(szTemp, nStrLen, szStr);
szTemp = szStr + nStrLen -1;


// First trim spaces on the right
while( (szTemp >= szStr) && (*szTemp == ' ') )
*szTemp = '\0';//Здесь и возникает ошибка

Какой-то хитровыдуманный способ. Но впринципе дожно работать. Только здесь надо
Код
szTemp = szTemp + nStrLen -1;

и можно попрощаться с началом строки - хрен потом найдёшь. Ну да ладно.
И проверять надо, чтоб nStrLen!=0. И чтоб строка из одних пробелов не состояла - то начало-то потеряялось.
И цикл чуть-чуть переделать
Код

// while( /*(szTemp >= szStr)  один чёрт не срабатывает*/ && (*szTemp == ' ') )
//   *szTemp = '\0';//Здесь и возникает ошибка
while (*szTemp==' ') *(szTemp--)=0;

Атак всё круто. Иногда даже будет работать

PM MAIL ICQ   Вверх
AndyY
Дата 5.7.2004, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 316
Регистрация: 8.5.2004
Где: СПб

Репутация: 2
Всего: 4



думаю действительно lpCmdStr лежит на страничке с атрибутами PAGE_READONLY и при попытке ее модифицировать и происходит exception.

надо не так:
szTemp = szStr + nStrLen -1;
а так:
szTemp = szTemp + nStrLen -1;

только начало строки действительно теряем


--------------------
PM MAIL WWW   Вверх
Royan
  Дата 5.7.2004, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



2Nimbus
Твоя мысль ясна и поэтому я несколько переделал алгоритм, дабы избавиться от подобных недорозумений, и хоть он получился несколько плосковатым, зато по-мойму стал более безопасным

2p0s0l
Ради одной функции StrTrim подрубать библу слишком жирно wink.gif

2Олег М
Насчет nStrLen!=0 согласен, но менять условия цикла я не стал, так как есть вероятность того что байт перед 0-м символом строки тоже окажется пробелом и тогда будем считать левые пробелы лежащие где - то там...

2AndyY
Цитата
думаю действительно lpCmdStr лежит на страничке с атрибутами PAGE_READONLY и при попытке ее модифицировать и происходит exception.

Не думаю, я в одном случае получаю строчку из "Configuration Properties > Debugging > Command Arguments" проекта, а второй раз из самой командной строки, а результат один и тот же.

Это сообщение отредактировал(а) Royan - 6.7.2004, 14:45


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Nimbus
  Дата 6.7.2004, 00:07 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











И что, это работает?! wow.gif
Код
szTemp = szStr + nStrLen -1;

А где же тип переменной szTemp? ...хотя, если она была уже объявлена где-то...
И вот это ещё:
Код
int nLastPos = nStrLen;

В данном случае, IMHO, переменная nLastPos ВСЕГДА будет равна 0 (что-то я не просёк, где nStrLen присваивается хоть что-то после инициализации нулём). Но, как я подозреваю, задумка была совсем иной! hehe.gif
Остальное проверю завтра, а то поздно уже... rolleyes.gif
  Вверх
Nimbus
Дата 6.7.2004, 00:10 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











...да, похоже на сервере со временем что-то (на моих часах 01:11)???
  Вверх
Nimbus
Дата 6.7.2004, 00:12 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











...да, похоже на сервере со временем что-то (на моих часах 01:11)???
  Вверх
Олег М
Дата 6.7.2004, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 436
Регистрация: 10.6.2004
Где: Москва

Репутация: 7
Всего: 7



Цитата
Вобщем вот в итоге что я изобрел:

Да уж, точно - изобрёл. Велосипед с треугольными колёсами. Ты её хоть скомпилировал? О запуске речи пока и не идёт

PM MAIL ICQ   Вверх
Royan
Дата 6.7.2004, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Прошу прощения вот правильный вариант (то что выше писалось на работе из головы поэтому и наделал ошибок)

Цитата
LPSTR CMyStrFormat::mMyTrim(LPSTR szStr){
 
 
if(szStr ==  0){
   
return '\0';
  }

  size_t nStrLen = 0;
//Total string length
 
 
StringCchLength(szStr, 4096, &nStrLen); 

  LPSTR szTemp = szStr + nStrLen -1;

  size_t nLastPos = nStrLen;

 
// Count spaces on the right
 
while( (szTemp >= szStr) && (*szTemp == ' ') ){
    szTemp--;
    nLastPos--;
  }

 
//If string contained only paces return '\0'
 
if(nLastPos == 0){
   
return '\0';
  }


  szTemp = szStr;
 
int nCurPos = 0;

 
// Now count spaces on the left
 
while (*szTemp == ' '){
    nCurPos++;
    szTemp++;
  }

 
//The lenght of the trimmed string
 
size_t nTrimmedStrLen = nStrLen - nCurPos - (nStrLen - nLastPos);
  szFormattedStr =
new CHAR[nTrimmedStrLen];

 
  VALID_GLE_EX(szFormattedStr ,"Not enough memory. Please close other applications and try again.",
false);
 

 
//Copy the resulting trimmed string

 
while (nTrimmedStrLen > 0){
    nTrimmedStrLen --;
    *szFormattedStr++ = *szTemp++;
  }

  *szFormattedStr = '\0';
//Terminating NULL character
 
szFormattedStr-=(nStrLen - nCurPos - (nStrLen - nLastPos));//Rollback to the begining of the string
 
return szFormattedStr;
}


Это сообщение отредактировал(а) Royan - 7.7.2004, 14:02


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Олег М
Дата 6.7.2004, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 436
Регистрация: 10.6.2004
Где: Москва

Репутация: 7
Всего: 7



Нормально только надо {if(nLastPos == 0) { return ""; }

как вариант (тоже из головы) - почти тоже самое
Код
static TCHAR _szEmpty[]=_T("");
LPTSTR CMyStrFormat::mMyTrim(LPTSTR pszStr)
{
if (!szStr) return _szEmpty;

LPTSTR pszStart=pszStr,pszEnd;

for (;*pszStart==_T(' ');++pszStart);

int nLen;
StringCchLength(pszStart, 4096, &nLen)

for (psz1=pszStart+nLen;pszEnd!=pszStart && *pszEnd=_T(' '); --pszEnd);

if (pszStart==pszEnd) return _szEmpty;

nLen=pszEnd-pszStart;
TCHAR *pszRes=new TCHAR[nLen+1];
memcpy(pszRes,pszStart,nLen*sizeof(TCHAR));
pszRes[ nLen+1]=0;
return pszRes;
}



PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1105 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.