Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Непонятки с функцией Oemtochar()...
Форум программистов > Системное программирование > C, С++ и С Builder > Borland C++ Builder & Kylix
LAW
Есть вот такой вот код...
//---------------------------------------------------------------------------
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;

Тут начались проблемы. sad.gif
Если раскоминтарить текст "// delete tmp;" То мгновенно получаем Access Violation. На всех типах процессоров.
Если оставить закоминтареным то получаем Acess Violation при выходе из подпрограммы после выполнения строки "delete cStrLst;" причём (!!!) только на AMD процессорах. На интеле всё выполняется без ошибок.
Незнаю что делать, хоть самописную конвертилку в Ansi пиши. sad.gif
Kmet
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;

Подумай, какую память ты пытаешься освободить.
LAW
Честно говоря "логично что падает" для меня совсем не логично.
Ну закоментарил я освобождение, но почему при выходе из функции-то она падает?
Pasha
Замени
tmp=aParamBuf[2][0].c_str();
OemToChar(tmp,tmp);

на
OemToChar(aParamBuf[2][0].c_str(),tmp);

А то сейчас ты и буффер теряешь, и начальную строку напрямую меняешь (из за этого и падает, скорее всего).
LAW
Сделал предложенное, компилятор принял.

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

Интересно ещё то, что выпадает он всё время на разном кол-ве записей в БД, где-то в районе 190-210.
Короче дело тёмное.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2008 IPS, Inc.