Не понятные проблемы в классе. WideString - одна на всех? Или может я не понял???
struct T{
EmployeeStatus status;
long employeesid;
int id;
BSTR name;
BSTR group;
BSTR str;
long pointid;
TTimer *timer;
void __fastcall timerevent(TObject *Sender);
TRemouteModuleImpl *ra;
TdmMain *dm;
T(unsigned long time = 0);
~T();
unsigned long timein;
unsigned long timeout;
unsigned long duration;
};
T::T(unsigned long time){
id = 0;
name = WideString("");
group = WideString("");
str = WideString("");
pointid = 0;
timer = NULL;
dm = NULL;
timein = time;
timeout = 0;
duration = 0;
}
T::~T(){
delete timer;
delete dm;
timer = NULL;
dm = NULL;
}
typedef vector<T>E;
естественно есть форма - которая отображает данные этого класса:
{
....
private:
E employeeV;
public: // User declarations
__fastcall TfmMain(TComponent* Owner);
long __fastcall Login(TnRemouteModuleImpl *ea,BSTR login,long pointid,BSTR pass);
есть собственно функция - точнее две - одна рабочая вторая логирует
dmMain = new TdmMain(NULL);//Создаем датамодуль
LogEventsE(-1,-1,login,NULL);//пишем в лог - что ктото хочет залогинится
WideString temp = "Provider=SQLOLEDB.1;Password="+WideString(pass)+";Persist Security Info=True;
User ID="+WideString(login)+";Initial Catalog=#######;Data Source="+WideString(Server)+";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;
Use Encryption for Data=False;Tag with column collation when possible=False";//Формируем строку подключения
//Передаем имя и строку в дата модуль
if(!dmMain->SetConnect(login,temp)){
return -1;
}
//Если все путем - увеличиваем колво юзеров
employeenumb++;
//Помещаем класс и заполняем параметры
employeeV.push_back(T(lasttimesec));
employeeV.back().str = temp;
employeeV.back().status = LoginE;
employeeV.back().ra = ea;
employeeV.back().dm = dmMain;
employeeV.back().name = login;
employeeV.back().pointid = pointid;
employeeV.back().dm->ado1->Parameters->ParamByName("@login")->Value = employeeV.back().name;
//А вот здесь фигня начинается. employeeV.back().dm->ado1->ExecProc();
employeeV.back().group = WideString(employeeV.back().dm->ado1->Parameters->ParamByName("@###########")->Value);
employeeV.back().id = employeeV.back().dm->ado1->Parameters->ParamByName("@########")->Value;
employeeV.back().dm->ado2->Parameters->ParamByName("@########")->Value = employeeV.back().id;
employeeV.back().dm->ado2->ExecProc();
employeeV.back().employeesid = employeeV.back().dm->ado2->Parameters->ParamByName("@sessionid")->Value;
//Функция которая выдает ошибку LogEventsE(employeeV.back().employeesid,employeeV.back().id,employeeV.back().name,employeeV.back().status);
employeeV.back().ra->Fire_OnLogin(login,employeeV.back().group,employeeV.back().id,employeeV.back().employeesid);
employeeV.back().dm->ado3->Parameters->ParamByName("@id")->Value = employeeV.back().id;
employeeV.back().status = WaitMessageE;
employeeV.back().dm->ado3->Active = true;
//Функция которая выдает ошибку LogEventsE(employeeV.back().employeesid,employeeV.back().id,employeeV.back().name,employeeV.back().status);
if(employeeV.back().dm->ado3->RecordCount)
employeeV.back().ra->Fire_OnNewMessage(employeeV.back().id);
return employeeV.back().employeesid;
}
//--------Запись данных в лог и отображение на экране----------
void __fastcall TfmMain::LogEventsE(int SID,int ID, const WideString Name,EmployeeStatus Status){
String Task;
if(SID < 0){
Task = IntToStr(SID)+"\t "+IntToStr(ID)+" \t"+WideCharToString(Name)+"\t Connectig..."+"\t"+DateTimeToStr(Now());
}
else{
String status;
switch(Status){
case LoginE: status="Login";break;
case Sending: status ="Sending";break;
case Sent: status = "Send";break;
case Wait: status = "Wait";break;
case Receiving: status = "Receiving";break;
case Received: status = "Received";break;
case SendMessageE: status = "SendMessage";break;
case ReceiveMessage: status = "ReceiveMessage";break;
case WaitMessageE: status = "WaitMessage";break;
case LoginOutE: status = "LoginOut";break;
}
Task = IntToStr(SID)+"\t"+IntToStr(ID)+"\t"+ WideCharToString(Name)+"\t"+status+"\t"+DateTimeToStr(Now());
}
lbList->Items->Add(Task);
ofstream filelog("logevents.log",ios::app);
filelog << Task.c_str()<<"\n";
filelog.close();
}
Все работает хорошо. Кроме одного. В логе мне отображается после подключения не имя пользователя - как должно - а почему то имя группы, причем абсолютно верное. То есть:
01.11.2005 2:23:58 Вася Пупкин Connect sucesfull
01.11.2005 2:23:58 Вася Пупкин User is login
//Вот ошибка - должен быть Вася Пупкин - а почему- то выводится имя его группы.
//т.е. вместо name - group
14 1 Галимый юзер Login 01.11.2005 2:23:58
14 1 Галимый юзер WaitMessage 01.11.2005 2:23:58
Блин ничего не понимаю. Проверил все - процедура возращающая группу и ид - работает прекрасно. Но имя пользователя куда пропадает? Если возникает такой глюк - значит что то гдето я забыл?
Да все что в моем сообщении не объявлено - в реальном коде объявлено ВСЕ. Просто полный листинг не приводил - весьма велик.
Получается достаточно странная ситуация. Есть код.
struct T{
...
BSTR name;
BSTR group;
BSTR str;
...
};
T::T(unsigned long time){
...
name = WideString("");
group = WideString("");
str = WideString("");
...
}
...
Знатоки С++ АУ!? BSTR форева, а куда после конструктора девается объект WideString?
Знатоки С++ АУ!? BSTR форева, а куда после конструктора девается объект WideString?
Сделал так:
ZeroMemory(name,0);
..
ничего не изменило.
Сделал так:
ZeroMemory(name,0);
..
ничего не изменило.
Блин. Туплю. Вобщем если выкинуть иницыализацию из конструктора класса и использовать функции для копирования строк- получается такая картина -
вот этот код выполняется:
employeeV.back().status = LoginE;
employeeV.back().ra = ea;
employeeV.back().dm = dmMain;
а при попытке обращения к полю name - вылетает ошибка - банальная ошибка доступа.
Нифига не понимаю.
Блин. Туплю. Вобщем если выкинуть иницыализацию из конструктора класса и использовать функции для копирования строк- получается такая картина -
вот этот код выполняется:
employeeV.back().status = LoginE;
employeeV.back().ra = ea;
employeeV.back().dm = dmMain;
а при попытке обращения к полю name - вылетает ошибка - банальная ошибка доступа.
Нифига не понимаю.
Чем дальше в лес - тем толще партизаны. Видимо всеж надо идти спать (пить, выть, курить) :) нужное подчеркнуть. Если в классе поля сделать типа WideString - все работает. ПОЧЕМУ? В чем моя ошибка в использовании BSTR?
Если в классе поля сделать типа WideString - все работает. ПОЧЕМУ? В чем моя ошибка в использовании BSTR?
BSTR - указатель на wchar_t (могу ошибится, но наверняка где-то глубоко в хедерах есть #define wchar_t* BSTR). Ты делаешь:
что вполне допускает класс WideString, но ТЫ делаешь это в конструкторе т.е. - локально, а повыходе из конструктора где объект(который хранит саму строку)? Нету! В первом случае читал мусор, а во втором AV.
BSTR - указатель на wchar_t (могу ошибится, но наверняка где-то глубоко в хедерах есть #define wchar_t* BSTR). Ты делаешь:
что вполне допускает класс WideString, но ТЫ делаешь это в конструкторе т.е. - локально, а повыходе из конструктора где объект(который хранит саму строку)? Нету! В первом случае читал мусор, а во втором AV.
Сенкс. Я как-то не сообразил - что любая иницализация в конструкторе указателя в конечном итоге обречена :) Что в принципе никак не помешало мне обнулить указатели на другие объекты. Инерция.
Сенкс. Я как-то не сообразил - что любая иницализация в конструкторе указателя в конечном итоге обречена :) Что в принципе никак не помешало мне обнулить указатели на другие объекты. Инерция.
ИМХО для BSTR лучший метод выделения памяти - SysAllocString
OLECHAR FAR* sz
Allocates a new string and copies the passed string into it. Returns NULL if insufficient memory exists or if NULL is passed in.
Parameter
sz
A zero-terminated string to copy.
Return Value
If successful, points to a BSTR containing the string. If insufficient memory exists or sz was NULL, returns NULL.
Strings created with SysAllocString should be freed with SysFreeString.
Example
{
SysFreeString(m_bstrMsg);
m_bstrMsg = SysAllocString(sz);
}