Непонятки с функцией Oemtochar()...

  • Автор темы LAW
  • Дата начала
L

LAW

Гость
#1
Есть вот такой вот код...
Код:
//---------------------------------------------------------------------------
void CrtDBList(AnsiString cFilePth)
// Создаём таблицу перечня БД, входящих в группы, если этой таблицы еще нет:
{
AnsiString cEOL="";
if (QryDropTbl(3,"DBLIST"))
{
ShowMessage("Таблица DBLIST занята другим пользователем. Операция невозможна!");
return;
}

QryCrtTbl(3,"CREATE TABLE DBLIST (DB_NO INTEGER,BSEID CHAR(10),BSENME CHAR(100),"+cEOL+
+"ISBANK LOGICAL,GRPBNK LOGICAL,SHRIMG LOGICAL,ALTCAGENT LOGICAL,ALTGOODS LOGICAL,"+cEOL+
+"ADDDOC LOGICAL,SHRDIR CHAR(70),NETDIR CHAR(70),LOCDIR CHAR(70),IMGDIR CHAR(70));"+cEOL+
+"CREATE INDEX BSEID ON DBLIST (BSEID)");

// Создаем ListBox для TXT.dir:
TListBox *cStrLst=new TListBox(ControlPanel);
cStrLst->Visible=false;
cStrLst->Items->LoadFromFile(cFilePth);

// Формируем перечень параметров БД:
const int nPBIndCnt=14;
AnsiString aParamBuf[nPBIndCnt][5]={{"","DB_NO","[Database","N","0"},
{"","BSEID","DtbsID=","C","''"},
{"","BSENME","Name=","C","''"},
{"","ISBANK","IsBank=","B","Off"},
{"","GRPBNK","GrpBnk=","B","Off"},
{"","SHRIMG","ShrImg=","B","Off"},
{"","ALTCAGEN","AltCagent=","B","Off"},
{"","ALTGOODS","AltGoods=","B","Off"},
{"","ADDDOC","AddDoc=","B","Off"},
{"","SHRDIR","Shared=","C","''"},
{"","NETDIR","Network=","C","''"},
{"","LOCDIR","Local=","C","''"},
{"","IMGDIR","Images=","C","''"}};


// Строка для формирования значений реквизитов для INSERT:
AnsiString cWrk,cCurPrmVal;
int nPos;
for (int nRecInd=0;nRecInd<cStrLst->Count;nRecInd++)
// Цикл по кол-ву строк в TXT.dir:
{
for (int nPrmInd=0;nPrmInd<nPBIndCnt;nPrmInd++)
// Цикл по кол-ву строк в aParamBuf:
{
// Опредеяем, содержит ли очередная строка TXT.dir ключевое слово
// из текущей строки aParamBuf:
nPos=cStrLst->Items->Strings[nRecInd].Pos(aParamBuf[nPrmInd][2]);
if (nPos > 0)
// Очередная строка TXT.dir содержит ключевое слово из текущей
// строки aParamBuf.
// Приступаем к формированию значения соответствующего поля DBLIST:
{
if (aParamBuf[nPrmInd][2] == "[Database")
// Для параметра [Database спец.обработка - заносим в aParamBuf № БД:
{
aParamBuf[nPrmInd][0]=cStrLst->Items->Strings[nRecInd].SubString(10,(cStrLst->Items->Strings[nRecInd].Pos("]")-10));
if (nRecInd > 0)
WrtToDBList(aParamBuf);
}
else
// Для остальных параметров заносим в aParamBuf значение после символа "=":
aParamBuf[nPrmInd][0]=cStrLst->Items->Strings[nRecInd].SubString(nPos+aParamBuf[nPrmInd][2].Length(),((cStrLst->Items->Strings[nRecInd].Length()+1)-nPos));
}
}
}

WrtToDBList(aParamBuf);
delete cStrLst;
//---------------------------------------------------------------------------
void WrtToDBList(AnsiString aParamBuf[14][5])
// Запись очередной строки в таблицу DBLIST.
{
AnsiString cWrk;
const int nPBIndCnt=14;

// Пустые параметры (не запоненные в TXT.dir) заполняем значениями
// по-умолчанию:
for (int nPrmInd=0;nPrmInd<nPBIndCnt;nPrmInd++)
{
if (aParamBuf[nPrmInd][0]=="")
aParamBuf[nPrmInd][0]=aParamBuf[nPrmInd][4];
}

char *tmp=new char(aParamBuf[2][0].Length()+1);
// Переводим имя базы в ANSI
tmp=aParamBuf[2][0].c_str();
OemToChar(tmp,tmp);
aParamBuf[2][0]=tmp;
// delete tmp;

for (int nPrmInd=0;nPrmInd < nPBIndCnt;nPrmInd ++)
{
if (aParamBuf[nPrmInd][3]=="N")
cWrk=cWrk + aParamBuf[nPrmInd][0]+",";
else if (aParamBuf[nPrmInd][3]=="C")
cWrk=cWrk + "'"+aParamBuf[nPrmInd][0]+"',";
else if (aParamBuf[nPrmInd][3]=="B")
{
if (aParamBuf[nPrmInd][0]=="On")
cWrk=cWrk + "TRUE,";
else if (aParamBuf[nPrmInd][0]=="Off")
cWrk=cWrk + "FALSE,";
else
ShowMessage("Неверный параметр "+aParamBuf[nPrmInd][0]);
}
}
ControlPanel->qryDBList->SQL->Clear();
ControlPanel->qryDBList->SQL->Add("INSERT INTO DBLIST (DB_NO,BSEID,BSENME,ISBANK,GRPBNK,SHRIMG,ALTCAGENT,ALTGOODS,ADDDOC,SHRDIR,NET
DIR,LOCDIR,IMGDIR)");
// cWrk.SubString для удаления последней запятой в списке значений параметров.
ControlPanel->qryDBList->SQL->Add("VALUES ("+cWrk.SubString(1,cWrk.Length()-1)+")");
ControlPanel->qryDBList->ExecSQL();

// Очистим значение текущего параметров перед заполнением из TXT.dir:
for (int nPrmInd=0;nPrmInd<nPBIndCnt;nPrmInd++)
aParamBuf[nPrmInd][0]="";
}
//---------------------------------------------------------------------------
Он был полностью рабочий, пока не понадобилось данные из текстовика перед внесением в базу конвертануть из OEM в ANSI.
Код:
char *tmp=new char(aParamBuf[2][0].Length()+1);
// Переводим имя базы в ANSI
tmp=aParamBuf[2][0].c_str();
OemToChar(tmp,tmp);
aParamBuf[2][0]=tmp;
// delete tmp;
Тут начались проблемы. :lol:
Если раскоминтарить текст "// delete tmp;" То мгновенно получаем Access Violation. На всех типах процессоров.
Если оставить закоминтареным то получаем Acess Violation при выходе из подпрограммы после выполнения строки "delete cStrLst;" причём (!!!) только на AMD процессорах. На интеле всё выполняется без ошибок.
Незнаю что делать, хоть самописную конвертилку в Ansi пиши. :(
 

Kmet

Well-Known Member
Java Team
25.05.2006
1 036
8
#2
Код:
char *tmp=new char(aParamBuf[2][0].Length()+1);
// Переводим имя базы в ANSI
tmp=aParamBuf[2][0].c_str();
OemToChar(tmp,tmp);
aParamBuf[2][0]=tmp;
// delete tmp;
логично что падает. на правильном компиляторе по идее это вообще не должно откопилироваться, с_str исходя из названия должна возвращать константный указатель. а проблема вот тут:

Код:
char *tmp=new char(aParamBuf[2][0].Length()+1);
tmp=aParamBuf[2][0].c_str();
delete tmp;
Подумай, какую память ты пытаешься освободить.
 
L

LAW

Гость
#3
Честно говоря "логично что падает" для меня совсем не логично.
Ну закоментарил я освобождение, но почему при выходе из функции-то она падает?
 
P

Pasha

Гость
#4
Замени
Код:
tmp=aParamBuf[2][0].c_str();
OemToChar(tmp,tmp);
на
Код:
OemToChar(aParamBuf[2][0].c_str(),tmp);
А то сейчас ты и буффер теряешь, и начальную строку напрямую меняешь (из за этого и падает, скорее всего).
 
L

LAW

Гость
#5
Сделал предложенное, компилятор принял.

Я тут уже многое перепробовал, и выясняется для меня, что дело не в OemToChar как я думал (кстати за правки приогромное спасибо!), тут какая-то проблема с работой с массивом строк aParamBuf. То ли дефрагментация памяти возникает из-за разной длинны перезаписываемых в него строк, то ли ещё какая хрень. Буду пробовать использовать не постоянный массив, а создавать для формирования каждой строки БД. Гемор конечно, но уже интересно стало что это баг работы с памятью в BORLANDMM, в которой возникает ацесс виолейшен или я криворукий.

Интересно ещё то, что выпадает он всё время на разном кол-ве записей в БД, где-то в районе 190-210.
Короче дело тёмное.