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

Тема в разделе "Borland C++ Builder & Kylix", создана пользователем LAW, 7 июн 2007.

  1. LAW

    LAW Гость

    Есть вот такой вот код...
    Код (Text):
    //---------------------------------------------------------------------------
    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.
    Код (Text):
    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 пиши. :(
     
  2. Kmet

    Kmet Well-Known Member

    Регистрация:
    25 май 2006
    Сообщения:
    1.017
    Симпатии:
    1
    Код (Text):
    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 исходя из названия должна возвращать константный указатель. а проблема вот тут:

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

    LAW Гость

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

    Pasha Гость

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

    LAW Гость

    Сделал предложенное, компилятор принял.

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

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

Поделиться этой страницей