C++ Pass-by-reference not working

Fox5

Diamond Member
Jan 31, 2005
5,957
7
81
So I have code that's supposed to do stuff to some matrices, but it doesn't appear to do anything at all. The logic of my code appears to work, but the values aren't actually passed back up to the referring variable.

//Calling code from main
for (int structNum = 0; structNum < 8; structNum++)
{
for (int x = 0; x < numthreads; x++)
{
tg.create_thread(boost::bind(&decompose::eek:ctagon,d,M,copy,x,structNum));
}
tg.join_all();
d->copy(copy,M);

//First method being called
void decompose::eek:ctagon(matrix4D & M, matrix4D & copy, int threadNum, int structNum)
{

switch(structNum)
{
case 0: n += erosion(M, M.m1, copy.m1, M.b0, threadNum);
case 1:n += erosion(M, M.m2, copy.m2, M.b1, threadNum);
case 2:n += erosion(M, M.m3, copy.m3, M.b2, threadNum);
case 3:n += erosion(M, M.m4, copy.m4, M.b3, threadNum);
case 4:n += erosion(M, M.m1, copy.m1, M.b4, threadNum);
case 5:n += erosion(M, M.m2, copy.m2, M.b5, threadNum);
case 6:n += erosion(M, M.m3, copy.m3, M.b6, threadNum);
case 7: n += erosion(M, M.m4, copy.m4, M.b7, threadNum);
default: n += 0;
}
}

//2nd method being called
int decompose::erosion(matrix4D &M,matrix<int> &m,matrix<int> &g,matrix<int> &structElem, int threadNum)
{
//set to 1 if a change occurs
int f = 0;
//Our structuring elements only have a radius of 1 pixel
int offset = 1;
//a temp matrix to store a submatrix
matrix<int> c;
c.resize(3,3);
//the position that our submatrix intersects the structuring element, a mask

int ok[2];
where(structElem, ok[0],ok[1]);

//Because the comparisons extend out one pixel from each center, we want to avoid the outside edges of the image
for (int x = threadNum+offset; x < (h - offset); x += num)
{
for (int y = threadNum+offset; y < (w-offset); y+= num)
{
//identify the masked region
//subrange function not implemented? use a case cludge instead then
//c = boost::numeric::ublas::subrange(m, x-offset, x+offset, y-offset, y+offset);
for (int a = 0; a < 3; a++)
for (int b = 0; b < 3; b++)
{
int xvalue;
int yvalue;
switch (a)
{
case 0: xvalue = x-offset;
case 1: xvalue = x;
case 2: xvalue = x+offset;
}
switch (b)
{
case 0: yvalue = y-offset;
case 1: yvalue = y;
case 2: yvalue = y + offset;
}
c(a,b) = m(xvalue,yvalue); //13 lines of code to implement 9 assignments
}

//check pixel values
if (c(1,1) >-1 && c(ok[0],ok[1]) > -1)
if (sameValue(M,x,y, x-1+ok[0], y-1 + ok[1]))
{
//erode the octagon
g(x,y) = g(x,y) +1;
f=1;
}
}
}
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
which call you are expecting the pass by reference to take effect? what variable is supposed to be modified? details like that help us to narrow down the bug more quickly :)

anyway if the problem is with void decompose:ctagon() and argument "M", it is not declared as a reference. edit: well, it wasn't, anyway.
 

Fox5

Diamond Member
Jan 31, 2005
5,957
7
81
Whoops, I was playing around with the code to see if changing things would help.
The objects I want to modify exist in main. I'm passing them by reference to octagon, which then passes them by reference to erosion. Erosion changes some values, but those values never make it back to the structures in main. I've checked and copy and M do exist at separate locations in memory, so I'm not sure why their values wouldn't change.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Does the pass-by-reference work if you call the function directly from the main thread? What if you try using pointers instead of references?
 

Fox5

Diamond Member
Jan 31, 2005
5,957
7
81
The problem appears to be in the call from main:
tg.create_thread(boost::bind(&decompose:eek:ctagon,d,M,copy,x,structNum));


It seems like either the create_thread function of boost::threadgroup or the boost::bind function do not properly deal with references. (I'm using the boost linear algebra and threading libraries)
Changing the call to d->octagon(M,copy,x,structNum) causes it to work...at least for that part. I'm still having troubles later in my code where it isn't producing the correct output, plus it takes way too long to run.
 

Fox5

Diamond Member
Jan 31, 2005
5,957
7
81
Ok, apparently boost::bind doesn't pass by reference unless explicitly requested.
Adding boost::ref() around each parameter passed by boost::bind causes that code to work correctly. Now to track down the rest of my errors....
 

Fox5

Diamond Member
Jan 31, 2005
5,957
7
81
Well, the speed difference between the multi-threaded implementation of this code and the single-threaded appears to be in the use of boost::matrix versus straight up arrays. Adding the -DNDEBUG command when compiling seems to eliminate the speed difference though, so I guess the matrix class must have a lot of debugging stuff turned on by default. Well, at least the speed difference is gone for small data sets, the old single threaded code won't even run for data sets larger than 511x511x4, though that could possibly be taken care of.