-1
static T MultiplyElement(const Matrix& matrixA, const Matrix& matrixB, 
    unsigned M2col, unsigned M1row)
{
    T sumToReturn = 0;

    for (unsigned iM1colM2row = 0; iM1colM2row < matrixA.m_n; iM1colM2row++)
    {
        sumToReturn += 
            matrixA.m_data[M1row][iM1colM2row] * matrixB.m_data[iM1colM2row][M2col];
    }

    return sumToReturn;
}

...

    std::vector<std::thread> threads;
    for(unsigned i = 0; i < outM ; ++i)
    {
        for(unsigned j = 0; j < outN; ++j)
        {
            threads.push_back(std::thread([&]()
            {
                outMatrix.m_data[i][j] = MultiplyElement(matrixA, matrixB, i, j);
            }
            ));
        }
    }
    for(auto& thread : threads)
    {
        thread.join();
    }

Compiled with: clang++ -std=c++11 -stdlib=libc++ newFile.cpp

I'm getting a segfault in MultiplyElement... any idea why?

user2588666
  • 821
  • 1
  • 7
  • 16
  • 3
    Well, did you step through the code in a debugger and examine the line of code that is throwing the error? Wrong Array Indexes maybe? This is not the "human debuggers" site. – OldProgrammer Jan 23 '14 at 20:50
  • If you remove the multithreading, the code produces the correct result--so that type of debugging is not what I am looking for. The bug is a product of using threads, and I'm not well-versed in C++11 threads, so I was looking for some community help :) – user2588666 Jan 23 '14 at 20:56
  • @user2588666 Race conditions maybe?? – πάντα ῥεῖ Jan 23 '14 at 20:57
  • In regards to race conditions, I created a variable to lock the thread on. And I tried locking before and unlocking after the outMatrix.m_.... = Multi... call, and I still get the segfault. – user2588666 Jan 23 '14 at 21:01
  • When I dropped the lambda, I got it to work... That must have been the root of the issue. – user2588666 Jan 23 '14 at 21:46

1 Answers1

2

I think the problem is with your capture. You are using reference-capture for all variables. You should be capturing i and j by value. Try [&, i, j] for your capture clause.

Edit: You can check the answer here. You have the same issue.

Community
  • 1
  • 1
François Moisan
  • 790
  • 6
  • 12
  • @CantChooseUsernames They are modified by the loop. But even then they are still locally scoped variables. If the threads are scheduled after one or both loops end, the call to MultiplyElement would be made with undefined values for M2Col and/or M1row – François Moisan Jan 23 '14 at 23:56
  • And passing by value is going to change that how? They will still be modified by the loop.. Whether the OP passes them by value or by reference, it's not going to make any difference here. The functions taking the variables I and J aren't modifying it and it will be getting the same value as pass by value. Btw, MultiplyElement takes I and J as pass by value already.. – Brandon Jan 24 '14 at 00:11
  • 2
    @CantChooseUsernames It doesn't matter if MultiplyElement takes them by value or not because `thread` will not be calling that function directly. It will do so through the lambda object. The lambda is the problem because it will have kept those ints by ref. By the time it is invoked, those ints could be long gone and junk will be read. – François Moisan Jan 24 '14 at 00:46
  • @Francois, unfortunately I cannot test this, as I had ditched my original code; however I am near certain this would have solved my problem. Definitely learned from this. Thanks! – user2588666 Jan 27 '14 at 14:17