multi-threaded bug

Тема в разделе "LANGS.C", создана пользователем baga, 14 окт 2007.

  1. baga

    baga New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    16
    Есть класс CParallelBellmanFord, при вызове некоторого метода запускается N потоков с телом WorkerThread

    Код (Text):
    1. void CParallelBellmanFord::WorkerThread()
    2. {
    3.     int rid;
    4.     bool runFlag;
    5.  
    6.     char* section = "\0";
    7.  
    8.     try
    9.     {
    10.         for(;;)
    11.         {
    12.             mMutex.Lock();
    13.             rid = -1;
    14.  
    15.             section = "Find region to update\0";
    16.  
    17.             for(uint i = 0; i < mNumRegions; i++)
    18.             {
    19.                 if(mRegions[i].update == 1)
    20.                 {
    21.                     mRegions[i].update = 0;
    22.                     rid = i;
    23.                     break;
    24.                 }
    25.             }
    26.  
    27.             runFlag = mRunFlag;
    28.             mMutex.Unlock();
    29.  
    30.             if(!runFlag)
    31.                 return;
    32.  
    33.             if (rid < 0)
    34.             {
    35.                 Sleep(10);
    36.                 continue;
    37.             }
    38.  
    39.             section = "Process region\0";
    40.  
    41.             SRegion& region = mRegions[rid];
    42.  
    43.             if(ProcessRegion(region))
    44.             {
    45.                 mMutex.Lock();
    46.  
    47.                 section = "Mark all regions\0";
    48.  
    49.                 for(uint i = 0; i < mNumRegions; i++)
    50.                     mRegions[i].update = 1;
    51.  
    52.                 mRegions[rid].update = 0;
    53.  
    54.                 mMutex.Unlock();
    55.             }
    56.         }
    57.     }
    58.     catch(const CException& ex)
    59.     {
    60.         FILE* f = fopen("WorkerThread.log", "a");
    61.         fprintf(f, "Exception: '%s' at '%s' line %d\nsection %s\n\n",
    62.             ex.GetText(), ex.GetFile(), ex.GetLine(), section);
    63.         fclose(f);
    64.     }
    65.     catch(...)
    66.     {
    67.         FILE* f = fopen("WorkerThread.log", "a");
    68.         fprintf(f, "Fatal error\nsection %s\n\n", section);
    69.         fclose(f);
    70.     }
    71. }
    72.  
    73. bool CParallelBellmanFord::ProcessRegion(const SRegion& region)
    74. {
    75.     bool flag = false;
    76.     const uint numEdges = region.edges.GetCap();
    77.     const uint numVertices = region.numVertices;
    78.  
    79.     char* section = "\0";
    80.     uint di = 0;
    81.     uint dj = 0;
    82.  
    83.     try
    84.     {
    85.         for(uint i = 0; i < numVertices; i++)
    86.         {
    87.             di = i;
    88.             for(uint j = 0; j < numEdges; j++)
    89.             {
    90.                 dj = j;
    91.  
    92.                 section = "uint id = region.edges[j]\0";
    93.                 uint id = region.edges[j];
    94.  
    95.                 section = "const SEdge& edge = mGraph->GetEdge(id)\0";
    96.                 const SEdge& edge = mGraph->GetEdge(id);
    97.  
    98.                 section = "if (mDistances[edge.src] >= MAX_INT)\0";
    99.                 if (mDistances[edge.src] >= MAX_INT)
    100.                     continue;
    101.  
    102.                 section = "int dist = mDistances[edge.src] + edge.weight\0";
    103.                 int dist = mDistances[edge.src] + edge.weight;
    104.  
    105.                 section = "if (dist >= mDistances[edge.dst])\0";
    106.                 if (dist >= mDistances[edge.dst])
    107.                     continue;
    108.  
    109.                 section = "mDistances[edge.dst] = dist\0";
    110.                 mDistances[edge.dst] = dist;
    111.  
    112.                 section = "mPredcessor[edge.dst] = edge.src\0";
    113.                 mPredcessor[edge.dst] = edge.src;
    114.                 flag = true;
    115.             }
    116.         }
    117.     }
    118.     catch(const CException& ex)
    119.     {
    120.         FILE* f = fopen("ProcessRegion.log", "a");
    121.  
    122.         fprintf(f, "Exception: '%s' at '%s' line %d\nsection %s\n",
    123.             ex.GetText(), ex.GetFile(), ex.GetLine(), section);
    124.  
    125.         fprintf(f, "numEdges=%d numVertices=%d\n",
    126.             numEdges, numVertices);
    127.  
    128.         fprintf(f, "region.numEdges=%d region.numVertices=%d i=%d j=%d\n\n",
    129.             region.edges.GetCap(), region.numVertices, di, dj);
    130.  
    131.         fclose(f);
    132.         throw ex;
    133.     }
    134.     catch(...)
    135.     {
    136.         FILE* f = fopen("ProcessRegion.log", "a");
    137.         fprintf(f, "Fatal error\nsection %s\n\n", section);
    138.         fclose(f);
    139.         throw;
    140.     }
    141.  
    142.     return flag;
    143. }
    Exception: 'id < mCap' at 'c:\projects\shortestpath\shortestpath\TArray.hpp' line 70
    section uint id = region.edges[j]
    numEdges=22350 numVertices=11288
    region.numEdges=11175 region.numVertices=5756 i=3335 j=11175

    Exception: 'id < mCap' at 'c:\projects\shortestpath\shortestpath\TArray.hpp' line 70
    section uint id = region.edges[j]
    numEdges=22350 numVertices=11362
    region.numEdges=11175 region.numVertices=5756 i=3386 j=11175

    Exception: 'id < mCap' at 'c:\projects\shortestpath\shortestpath\TArray.hpp' line 70
    section uint id = region.edges[j]
    numEdges=11175 numVertices=5757
    region.numEdges=7450 region.numVertices=3888 i=5595 j=7450

    -------------------------------------------------

    numEdges <> region.numEdges
    numVertices <> region.numVertices

    как такое возможно???
    прочитали значения структуры в начале кода и что произошло в конце (учитывая, что переменные и структура не изменяются)...
     
  2. planet

    planet New Member

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    108
    mMutex - ?
    может лучше критические сецкции использовать.
     
  3. baga

    baga New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    16
    это и есть крит секция
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Неправильно:
    Код (Text):
    1. char* section = "\0";
    Правильно:
    Код (Text):
    1. const char* section = "\0";
    Объект, для которого вызывается WorkerThread, один на все потоки, или уникален на каждый поток?

    Код (Text):
    1. SRegion& region = mRegions[rid];
    Почему это не под мутексом?
     
  5. baga

    baga New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    16
    Один класс - N потоков

    char* section = "\0"; это для отладки, значения не имеет

    SRegion& region = mRegions[rid];
    т.к. rid уникален и другой поток взять его не может и массив mRegions не изменяется то по идее lock не нужен

    ProcessRegion тоже не лочится (т.к. для алгоритма не важно в каком порядке потоки прочитают и изменят данные).

    Что происходит, если несколько потоков пытаются изменить переменную одновременно? Мне кажется что такого в любом случае не должно происходить.
     
  6. baga

    baga New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    16
    все, спасибо за внимание, проблема решена