Builder C++. Компилирование релиза, многопоточного.

Тема в разделе "LANGS.C", создана пользователем a9d, 27 ноя 2008.

  1. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Все время компилировал конечную версию программ использую след. алгоритм:
    1. Project/Options
    2. На вкладке Compiler выбираю Release
    3. На вкладке Packages убираю флажок "Build with runtime packages"
    4. На вкладке Linker убираю Use Dynamic RTL
    5. Компилирую.

    Проблем с запуском на других компах не было.
    Написал прогу с одним дочерним потоком, поток создавал функцией _beginthread , собрал на компах с билдером пашет. А на компах без билдера вылетает после захода в поток, на некоторых просто выдает ошибку мол прога лезит не по тому адресу.

    Как в такой ситуации нужно компилить?

    ЗЫ: Поток прост и безобиден. В нем ошибки нет.
     
  2. osrootd

    osrootd New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2008
    Сообщения:
    1.086
    Извините, конечно, я не Windows программист, но вот у нас, например для потоков нужна libpthread.so
    Может у вас тоже потоки создаются другой либой, не включенной в поставку билдера?

    Память не может быть read

    у вас тогда в коде ошибка. Давайте сорец, буим смотреть
     
  3. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Поток в память не лезет. Он просто фоново вертится в цикле. Эта ошибка вылетает в месте где создаться поток. Походу система обращается по какому-то адресу к функции а там ничего нет.
     
  4. osrootd

    osrootd New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2008
    Сообщения:
    1.086
    Он и так уже там.

    У тебя либо Access Violation либо read ()
    Ну пожалуйста, дай мне код.
     
  5. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Создание потока
    Код (Text):
    1.     if(T==1){
    2.        btnStop->Enabled=True;
    3.        hTread=_beginthread(CreateOut, 0, NULL );  
    4.     }
    Поток
    Код (Text):
    1. //Производит выборку координат
    2. //На входе:
    3. //На выходе:
    4. void  CreateOut(void* pParams)
    5.  {
    6.    //Определяем минимум и максимум функции
    7.    //используется при фильтрации
    8.     float X1=0;  //входные данные
    9.     float X2=0;
    10.     float h=0;
    11.     float z0=0;
    12.  
    13.     //Инициализация значений
    14.     X1=StrToFloat(Form1->txtX1->Text);
    15.     X2=StrToFloat(Form1->txtX2->Text);
    16.     h=StrToFloat(Form1->txtH->Text);
    17.     z0=StrToFloat(Form1->txtZ0->Text);
    18.  
    19.     //Определяем максимум(минимум) функции по Z
    20.     float max=0,min=0,Buff=0;
    21.  
    22.     max=h+z0;
    23.     min=z0;
    24.     if(min>max){
    25.        Buff=min;
    26.        min=max;
    27.        max=Buff;
    28.      }
    29.  
    30.    //Обрабатываем файл
    31.    //открываем необходимые файлы
    32.    AnsiString str1=Form1->txtOpen->Text;  //файл с примером
    33.    AnsiString str2=Form1->txtSave->Text;  //сохраняем в
    34.  
    35.    std::ifstream MyIn(str1.c_str(),std::ios::in);
    36.    std::ofstream MyOut(str2.c_str(),std::ios::out);      //выход
    37.  
    38.    //Пройтись по файлу
    39.    char str[254]; //буффер для строки
    40.    char Doc4[]="( 4/";  //начало блока с координатами
    41.    char EndDoc[]=" )";
    42.    int index=0,index1=0,len=0;   //счетчик узлов
    43.    int lenBuf=0;  //длина блока
    44.    float TestX=0,TestZ=0; //текущие координаты
    45.  
    46.    MyIn.seekg(0);         //перемещаемся в начало файла
    47.  
    48.      while(1)  //поиск нужного участка
    49.     {
    50.        MyIn.getline(&str[0],254);
    51.  
    52.            if(strcmp(str,Doc4)==0) //ищем участок с координатами
    53.            {
    54.                   while(1)
    55.                    {
    56.                      MyIn.getline(&str[0],254);
    57.  
    58.                      if(strcmp(str,EndDoc)==0) //Проверить на достижение конца
    59.                   break;
    60.  
    61.                      //Выделить координаты из общей массы и пронумеровать
    62.  
    63.                      len=strlen(str);//определяем длинну строки
    64.  
    65.                      int j=0,k=0;  //положение в строке
    66.                      char CoordX[16]={0};
    67.                      char CoordY[16]={0};
    68.                      char CoordZ[16]={0};
    69.  
    70.                      for(int i=0;i<(len-2);i++)
    71.                        {
    72.                          //выделить X
    73.                          for(i;i<len;i++)
    74.                            {
    75.                              if(str[i]!=' ')
    76.                                {
    77.                                   if(str[i]!='/')
    78.                                     {
    79.                                       CoordX[k]=str[i];
    80.                                       k++;
    81.                                     }
    82.                                }else break;
    83.                            }
    84.                           CoordX[k]=0;    //признак конца строки
    85.                           k=0;
    86.  
    87.                          i++;  //переходим на следующий символ
    88.  
    89.                          //выделить Y
    90.                          for(i;i<len;i++)
    91.                            {
    92.                              if(str[i]!=' ')
    93.                                 {
    94.                                   if(str[i]!='/')
    95.                                     {
    96.                                       CoordY[k]=str[i];
    97.                                       k++;
    98.                                     }
    99.                                 }
    100.                              else break;
    101.                            }
    102.                            CoordY[k]=0;
    103.                            k=0;
    104.  
    105.                            i++; //переходим на следующий символ
    106.  
    107.                          //выделить Z
    108.                          for(i;i<len;i++)
    109.                            {
    110.                              if(str[i]!=' ')
    111.                                 {
    112.                                   if(str[i]!='/')
    113.                                     {
    114.                                      CoordZ[k]=str[i];
    115.                                      k++;
    116.                                     }
    117.                                 }
    118.                              else break;
    119.                            }
    120.                            CoordZ[k]=0;
    121.                            k=0;
    122.  
    123.                           index++;  //индекс узла
    124.                           Form1->Edit3->Text=IntToStr(index); //отображаем текущий индекс
    125.  
    126.                           //обрезать по X и Z
    127.                           TestX=StrToFloat(CoordX); //текущий Х
    128.                           TestZ=StrToFloat(CoordZ); //текущий Z  
    129.  
    130.                           //Фильтруем узлы в три этапа
    131.                           if(TestX>=X1 && TestX<=X2)     //По Х
    132.                              {
    133.                                if(TestZ>=min && TestZ<=max)    //По Z
    134.                                  {
    135.                                    if(TestCoord(TestX,TestZ,X1,X2,h,z0)) //если пренадлежит заданному участку
    136.                                      {
    137.                                         lenBuf+=IntToStr(index).Length()+1;  //длинна записанного блока
    138.  
    139.                                         if(lenBuf>=29000)  //максимальная длина не более 30000 байт
    140.                                           {
    141.                                             MyOut<<"\n\n\n"; //начинаем новый блок
    142.                                             lenBuf=0;
    143.                                           }
    144.  
    145.                                         index1++;
    146.                                         MyOut<<IntToStr(index).c_str()<<" "; //запись в файл
    147.                                         Form1->Edit1->Text=IntToStr(index1); //отображаем кол-во отобранных
    148.                                      }
    149.                                   }
    150.                               }
    151.                        } //end for
    152.                    }//end while
    153.                    break;
    154.                }//end if
    155.  
    156.         }//end while
    157.      Form1->btnStop->Enabled=False;
    158.  //+++
    159. }
    160. //----------------End CreateOut------------
    161.  
    162.  
    163. //Функция определяет пренадлежит ли узел заданному участку
    164. //На входе: проверяемые координаты, начальное условие
    165. //На выходе: да/нет
    166. int TestCoord(float X,float Z,float X1,float X2,float h,float z0)
    167.   {
    168.      float min=0,max=0,Buff=0,fZ=0;
    169.  
    170.      //получаем тестовое значение
    171.      fZ=z0+h*sin(3.14*(X-X1)/(X2-X1)); //Функция
    172.  
    173.      max=fZ;
    174.      min=z0;
    175.      if(min>max){          //определяем большее значение
    176.         Buff=min;
    177.         min=max;
    178.         max=Buff;
    179.        }
    180.  
    181.      //проверяем на принадлежность
    182.      int i=0;
    183.      if(Z>=min && Z<=max)
    184.        i=1;
    185.  
    186.     return i;
    187.   }
    188. //----------------End TestCoord------------
    Ошибка вызывается даже если поток пуст. Проблема не в коде.
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    А _stdcall кто будет указывать ?
    А-а, пардон, в _beginthread передается _cdecl ...
     
  7. osrootd

    osrootd New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2008
    Сообщения:
    1.086
    leo
    Значит все таки AccessViolation
     
  8. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    a9d
    Я в сях не спец, но _beginthread это CRT-шная функция и "This function is available only in the multithread libraries".
    Может лучше заюзать "родные" VCL-ные BeginThread или TThread ? Им то точно никаких multithread libraries не нужно
     
  9. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    leo
    А в Билдере все функции по умолчанию - не cdecl, а fastcall. Может, в этом вся проблема?
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    CyberManiac
    Да не-е, по умолчанию cdecl, а автогенерируемым заготовкам VCL-ных кликов автоматам приписывается _fastcall
    Если только сам ручками в настройках изменил на register, и то врядли, т.к. и передаваемый параметр не использ-ся, а при cdecl вызывающая прога сама стек чистит, ну и на компе с билдером вроде "пашет" :)

    PS: Вообще, BCB это какой-то странный гибрид :) В частности все (достаточно толковое) описание работы с тредами взято из дельфей и в основном касается TThread и мельком BeginThread, а описание сишной _beginthread существует само по себе, и не понятно что эта функция делает и можно ли ее юзать с VCL и Ansistring (для этого нужно как минимум установить переменную System::IsMultiThread = true).
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    a9d
    Наконец глянул код потока и ужаснулся ;) Прописная истина - визуальные VCL-компоненты не являются потокобезопасными, даже читать св-ва контролов из другого потока не рекомендуется, не говоря уже о записи - иначе возможны глюки. Лучше всего убрать из потока обращения к форме или на крайняк юзать для этого TThread.Syncronize (но это доп.тормоза, т.к. происходит переключение на основной поток)
     
  12. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Исключил обращение к форме.
    Добавил библиотеки borlndmm.dll , cc3260.dll , cc3260mt.dll. Эффекта ноль. Да и вообще вылетает даже пустой поток.

    ЗЫ: с _beginthreadNT тоже не пашет.
     
  13. Sov

    Sov New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2007
    Сообщения:
    20
    a9d
    Создавал и пустой и не пустой поток. Из потока и читает с компонент и пишет,все ок выложи целиком проект плз
     
  14. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    a9d
    Мда, тебе что нужно "шашечки или ехать", непременно "победить" некий _beginthread или чтобы прога работала ?
    Объясняю еще раз. Все вариации beginthread-ов являются обертками над виндовой CreateThread и выполняют доп.действия для обеспечения потокобезобасности используемых библиотек. Если пишешь на "чистом" С\С++ с CRT, то юзаешь CRT-шную _beginthread(ex). Если юзаешь MFC, то нужен AfxBeginThread или класс CThread. Если юзаешь VCL и AnsiString, то будь добр юзать System::BeginThread или класс TThread.
    C VCL можно и виндовую CreateThread юзать, если предварительно установить IsMultiThread = true, а в функции потока первым делом вызвать Set8087CW(Default8087CW) для инициализации FPU (если он юзается явно или неявно) и заключить тело функции в try\except (иначе в сл.ошибки вся прога слетит)
     
  15. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Все разобрался. Проблема была именно в AnsiString.