Danka |
Отправлено: 05.02.2004, 17:00 |
|
Не зарегистрирован
|
Привет. Я создала трёхуровневая программу. SQL_Server---Midas Server----ActiveX Client-Form. Я создаю весьма длиные и сложные SQL запросы (много join, group by, etc.). Запросы правильные, они выполняются, хотя долго. Но после выполнения запросов в IE Browser-e начинаються ошибки типа Acces Violation at "0x0...", Memory could not be read, etc. Ошибки не связаны ни с каким Event-ом. Иногда сразу появляются, иногда позже. От чего такие ошибки? От указателей? Вроде проверила. От чего ещё?
Спасибо. |
|
Ламер (редкий) |
Отправлено: 05.02.2004, 18:15 |
|
Не зарегистрирован
|
проверьте вашу прогу на наличие функций
strcpy, strcat strncpy и других
так как эти заразы не контролируют длину строк-аргументов,
за нефиг можно переполнить стек, если длина строки слишком велика |
|
Doga |
Отправлено: 05.02.2004, 19:13 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Подключи к проекту библиотеку CodeGuard (Project->Options->CodeGurd), откомпилируй (Full Debug) и запусти...
|
|
Danka |
Отправлено: 06.02.2004, 10:57 |
|
Не зарегистрирован
|
Я подключила к проекту библиотеку CodeGuard. В log-file вывелись ошибки типа :
у ActiveX Client-a:
Error 00001. 0x300010 (Thread 0x0D58):
Resource leak: The memory block (0x3C5A4CC) was never freed
The memory block (0x03C5A4CC) [size: 22 bytes] was allocated with SysGetMem
Call Tree:
0x036C9DDF
0x036AD32D
..............
y Midas Server-a:
Error 00001. 0x300010 (Thread 0x0D78):
Resource leak: The object (0xE49ED8) was never deleted
The object (0x00E49ED8) [size: 12 bytes] was created with new
Call Tree:
0x0040F38F(=PR_TRA~1.EXE:0x01:00E38F) c:\program files\borland\cbuilder6\include\atl\atlbase.h#5824
0x0040EA03(=PR_TRA~1.EXE:0x01:00DA03) c:\program files\borland\cbuilder6\include\atl\atlbase.h#2647
0x0040DBD4(=PR_TRA~1.EXE:0x01:00CBD4) c:\program files\borland\cbuilder6\include\atl\atlcom.h#3471
...........
и
Error 00002. 0x300010 (Thread 0x0D78):
Resource leak: The object array (0xE49D98) was never deleted
The object array (0x00E49D98) [size: 316 bytes] was created with new[]
Call Tree:
0x0040E70F(=PR_TRA~1.EXE:0x01:00D70F) c:\program files\borland\cbuilder6\include\atl\atlcom.h#3410
.............
У клиента я использую strtok в примерно таком коде:
AnsiString trunk_a;
if(CheckBoxTrunk_A->Checked)
trunk_a=strtok(ComboBoxTrunk_A->Text.c_str()," ");
AnsiString TSelectCpt::get_User()
{
LPTSTR lpszSystemInfo;
DWORD cchBuff = 1024;
TCHAR tchBuffer[1024];
lpszSystemInfo = tchBuffer;
//AnsiString userName;
if( GetUserName(lpszSystemInfo, &cchBuff) )
user=lpszSystemInfo;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 0);
int err = WSAStartup(wVersionRequested, &wsaData);
//AnsiString domen, comp;
if(err == 0)
{
char hn[1024];
struct hostent *adr;
if(gethostname((char *)&hn, 1024))
{
WSAGetLastError();
Beep();
}
adr = gethostbyname(hn);
if(adr)
{
comp=strtok(adr->h_name,".");
domen=strtok(NULL,".");
}
}
return user+"_"+comp+"."+domen+"_";
}
У клиента я создаю array из ТQRDBText
TQRDBText* TabTempText[3]={QRDBText1,QRDBText2,QRDBText3};
for(int i=0;i<3;i++)
{
TabQRText[i]=TabTempText[i];
TabQRText[i]->DataField="";
}
где
private: // User declarations
TQRDBText* TabQRText[3];
У сервера есть и array, и strtok в коде:
AnsiString c="1 16 17";//не больше 20 символов
AnsiString t[10];
int n=0;
if(AnsiCompareStr(c,"")!=0)
{
char *p;
p=strtok(c.c_str()," ");
do
{
t[n]=p;
p=strtok(NULL," ");
n++;
} while(p);
}
В переменых типа AnsiString я всатавляю очень большие строки. Это может вызвать ошибку? |
|
Doga |
Отправлено: 06.02.2004, 17:29 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
По сообщениям CodeGuard ты не освобождаешь выделенную некоторым переменным память — это плохо. Имена этих переменных придется искать в отладчике по их адресам.
Если для переменной выделена память оператором new[] — она должна быть освобождена оператором delete[].
Типа:
char *CC = new char[1000];
delete[] CC;
Проверь очистку памяти в деструкторах своих классов, которая была выделена при их инициализации или в ходе их работы.
Этот код доволно опасен:
char *p;
p=strtok(c.c_str()," ");
do
{
t[n]=p;
p=strtok(NULL," ");
n++;
} while(p);
c_str() возвращает указатель на локалный буфер класса AnsiString, который может быть изменён в любой момент(напр в другой процедуре, твоим клиентом иль сервером)
и тогда етот указатель уже будет не рабочий. Лучше сделать так:
char ссс[c.Legth() + 1];
StrLCopy(ccc, c.c_str(), c.Legth());
char *p;
p=strtok(ccc," ");
do
{
t[n]=p;
p=strtok(NULL," ");
n++;
} while(p);
Так лучше переделать для всех вызовов strtok.
Длина строки класса AnsiString может иметь неограниченню длину и занимать всю доступную память.
А пследствия работы программы дествительно похожи на выход за границы массива. Попробуй использовать только AnsiString и откажись от *char там где это возможно. А где невозможно — делай проверку на выход за границы массива.
|
|
Guest |
Отправлено: 06.02.2004, 18:00 |
|
Не зарегистрирован
|
Я не выделяю память оператором new[] ни для одной переменной, так что ошиба наверно не в этом. Указатели я только в том коде использую, в остальных случаях AnsiString.
Что меня беспокоит это то что я сделала новый ActiveX(чистый, один только TLabel) и он тоже даёт ошибки в CodeGuard-e и на моём компе, и на другом. ActiveX-ы выполняются на компе клента. В чем тогда ошибка? |
|
Danka |
Отправлено: 06.02.2004, 18:11 |
|
Не зарегистрирован
|
ой, я имя забыла написать в предыдущем сообщении |
|
Doga |
Отправлено: 09.02.2004, 14:22 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Так я не понял, ты ошибки , о которых сообщал CodeGuard, исправила?Он же собщил тебе адреса переменных!
Дальше. Если это не поможет включи в проэкте вывод ВСЕХ варнингов (по умолчанию не все выводятся) и внимательно изучи их — варнинги тож иногда мешают проге.
" Я не выделяю память оператором new[] ни для одной переменной" — я не представляю себе прогу без оператора new
А вообще не имея исходного кода, заочно, вряд ли чем можно помочь.
Придётся тебе самой, наверное сидеть в отладчике и выяснять что в проге происходит с твоими подозрительными переменными.
А почему ты решила, что именно те переменные подозрительные? Может ты ищешь не там, где потеряла а там, где светлей ?
|
|
Danka |
Отправлено: 10.02.2004, 09:15 |
|
Не зарегистрирован
|
Нет, я не исправила ошибки , о которых сообщал CodeGuard потому что я не знаю как это сделать, как найти переменную по её физическому адресу. Подскажи пожалуйста. |
|
Doga |
Отправлено: 11.02.2004, 15:08 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Оч просто. Перед компиляцией проэкта убедись что она пройдет в режиме полной отладки (Full Debug). Далее в тексте проги ставишь точку остановки напротив нужной тебе переменной и запускаешь проэкт в отладчике — программа в этом месте будет остановлена.
После чего наводишь курсор наеё имя и видишь хинт, типа: ABC = :011A5004 . 011A5004 — и есть адрес переменной ABC(в шестнадцатиричном виде). Осталось ток сравнить адрес этой переменной с тем адресом на который указывает CodeGuard. И если они вдруг совпадут, считай что ты сделаа это!
Вообще то CodeGuard будет выдавать свои сообщения с адресами когда ты уже не сможешь узнать адрес переменной, напр перед закрытием проги иль в конце работы функции, так что запиши себе адрес переменной в процессе её инициализации, а сравнивать будешь ток когда CodeGuard выдаст адрес.
Если ABC класс, то можно получить болле подробную информацию о его текущем состояниии в инспекторе отладки (Debug Inspector): щелкни на имени правой кнопкой мыши — появится всплывающая менюшка(вообще Debug Inspector работает с переменными всех типов). Выбери в ней пункт Debug — появится ещё одна менюшка и далее в ней выбери пункт Inspect... — тут то ты и увидишь тот самый инспектор отладки. Открывай закладку Properties и смотри. Если вместо значения свойства строка вроде: (read=... write=...) — щелкни на ней, а затем на появившийся "?" — увидишь текущее значение свойства.
А на будующее когда будешь писать очередную прогу советую поступать следующим образом: как только выделяешь память для Чего Либо, сразу напиши код для освобождения памяти от етого Либо Чаго! И ток потом пиши то что ты с етим Чаго Либо хочешь сделать. Проблем будет гораздо меньше!
Да! И незабуди перед очисткой памяти от Чаго Либо проверить есть ли оно вообще. А то бывают такие казусы, когда уже очищенную память очищаешь ещё и ещё раз! Последствя не предсказуемы!
И ещё.
УДАЧИ!!!
|
|
|