The strange thing, a local variable changes unexpectedly

[b][red]This message was edited by ntdll at 2007-2-1 1:30:51[/red][/b][hr]
[b][red]This message was edited by ntdll at 2007-1-31 1:35:5[/red][/b][hr]
Hi everyone.
I've got a really awful bug in my program.
The problem is a variable ('int j '), which controls the number of loops to be made. It changes unexpectedly, although there is nothing that can change it.If you could have a glance at my code (this strange thing occurs at line #74, after a rot(boxes); function call) this won't take much time for professional programmers..
In addition, i tried to change the variable by declaring another one with different name, but it didn't work. No functions that I use in that loop mustn't change the value of that variable.But they change in some way! The variables j, w, h, min_area change after the rot(boxes) function call. Maybe there is something wrong(I used pointers there)?
I mentioned about j, min_area, w, h variables in loop:
[CODE]
do{
for(j = 0; j < 16; j++){
w = calcWidth(boxes);
h = calcHeight(boxes);
if (min_area > w*h){
reset_min_area(min_area, w, h);
}
else if(min_area == w * h)
push_to_res(w, h);

rot(boxes);
}
}while (Permutate(boxes));
[/CODE]

If you watch those variables during the execution of a this loop, you will notice that their values change after rot() function call.
It shouldn't happen, because you can't access to variables outside the rot() function, since j, min_area, w, h are not global.

while executing the loop "for(j = 0; j < 16; j++){" I noticed following:(By using debugger)
At first loop j is 0, that's ok.
At second loop j is 1, but after the rot() function call it changes!!
and min_area, w, h change too!! ()

I don't know what to do with that.

Please, help!

Here is my code:

[CODE]
#include
#include
#include
#include

using namespace std;

struct TBox{
int
w,h,state,
id_number;
bool
Enabled;
} boxes[2][4];

struct point{
int x,y;
};

vector res;

operator<(const struct TBox& a, const struct TBox& b){
return a.id_number < b.id_number;
}
//=============


bool Permutate(struct TBox b[][4]);
int calcWidth(struct TBox b[][4]);
int calcHeight(struct TBox b[][4]);
void reset_min_area(int & min_area, int height, int width);
void push_to_res(int w, int h);
void Fill(struct TBox b[][4], int i);
void rot(struct TBox b[][4]);


int main(){

ifstream fin("packrec.in");
ofstream fout("packrec.out");
if(!fin || !fout){
cerr << "Error opening files" << endl;
return -1;
}

int
i,j,
min_area = 9000000,
w,h;
//reading input:
for(i = 0; i < 4; i++)
for(j = 0; j < 2; j++){
fin >> boxes[i][j].w;
fin >> boxes[i][j].h;
boxes[i][j].state = 0;//normal state.
}

//processing ( the main part ):
for (i = 0; i < 3; i++){//possible configs.
Fill(boxes, i);
do{
for(j = 0; j < 16; j++){//loop with a bug.
w = calcWidth(boxes);
h = calcHeight(boxes);

if (min_area > w*h){
reset_min_area(min_area, w, h);
}
else if(min_area == w * h)
push_to_res(w, h);

rot(boxes);//the strange thing occurs in this loop
}
}while (Permutate(boxes));
}

//Writing data to output file.

fout << min_area << endl;
j = res.size();
for(i = 0; i < j; i++){
fout << res[i].x << " " << res[i].y << endl;
}

return 0;
}
//-----------end of main() _---------------------------

bool Permutate(struct TBox b[][4]){
int i,j,k = 0;
TBox *pbox[4],box[4];
//collecting necessary data:
for (i = 0; i < 2; i++ )
for(j = 0; j < 4; j++){
if (b[i][j].Enabled){
box[k] = b[i][j];
pbox[k] = &b[i][j];
k++;
}

}
//permutating:
if ( next_permutation(box, box + 4) ){
for (i = 0; i < 4; i++) *pbox[i] = box[i];
return true;
}

return false;
}

void reset_min_area(int & min_area, int height, int width){//ok
min_area = width * height;
res.clear();
if (width > height){
int t = width;
width = height;
height= t;
}
struct point temp;
temp.x = width;
temp.y = height;
res.push_back(temp);//assume that w < h.
}

int calcWidth(struct TBox b[][4] ){//ok
int i,j,max_w = 0,width;
for(i = 0; i < 2; i++){
width = 0;
for(j = 0;j < 4; j++)
if (b[i][j].Enabled) width+= (b[i][j].state)? b[i][j].w:b[i][j].h;

if (max_w < width) max_w = width;
}
return max_w;
}

int calcHeight(struct TBox b[][4]){//OK
int i,j,max_h = 0,height;
for(i = 0; i < 4; i++){
height = 0;
for(j = 0;j < 2; j++)
if (b[j][i].Enabled) height+= (b[i][j].state)? b[i][j].h:b[i][j].w;

if (max_h < height) max_h = height;
}
return max_h;
}

void push_to_res(int w, int h){//OK
if (w > h){
int t = w;
w = h;
h = t;
}
struct point temp;
temp.x = w;
temp.y = h;
res.push_back(temp);//assume that w < h.
}

void Fill(struct TBox b[][4], int i){
int j,k,s;

switch (i){
case 0://1x4
j = 0;
for(k = 0; k < 4; k++)
b[0][k].Enabled = false;
for(k = 0; k < 4; k++){
b[1][k].Enabled = true;
b[1][k].id_number = ++j;
b[1][k].state = 0;//normal state.
}
break;
case 1://2x2
s = 0;
for(j = 0; j < 2; j++)
for(k = 0; k < 4; k++){
b[j][k].Enabled = false;
b[j][k].state = 0;
}
for(j = 0; j < 2; j++)
for(k = 0; k < 2; k++){
b[j][k].Enabled = true;
b[j][k].state = 0;
b[j][k].id_number = s++;
}
break;
case 2:/* two, one, one ( height )*/
for(j = 0; j < 2; j++)
for(k = 0; k < 4; k++){
b[j][k].Enabled = false;
b[j][k].state = 0;
}//null'em all !!!
b[0][0].Enabled = true;
b[0][0].id_number = 1;

for(j = 0; j < 3; j++){
b[1][j].Enabled = true;
b[1][j].id_number = j + 2;
}
break;
default:
cerr << "Error in functon Fill :)" << endl;
cerr << "The i value is:" << i << endl;
for (int cc = 0; cc < 2; cc++)
for(int dd = 0; dd < 4; dd++){
cerr << "boxes[" << cc << "][" << dd << "].state :" << boxes[cc][dd].state <<endl;
cerr << "boxes[" << cc << "][" << dd << "].Enabled :" << boxes[cc][dd].Enabled <<endl;
}
return ;
}
}

void rot(struct TBox b[2][4]){//
int a[4],idx = 0;
int ii,ij;
TBox * t[4];

for(ii = 0;ii < 2; ii++)
for(ij = 0; ij < 4; ij++){
if (b[ii][ij].Enabled){
a[idx] = b[ii][ij].state;
t[idx] = &b[ii][ij];
idx++;
}
}
for(ii = 0;ii < 4; ii++){
a[ii]++;
if(a[ii]==2){
a[ii] = 0;
a[ii + 1]++;
}
else break;
}

for(ii = 0; ii < 4;ii++) t[ii]->state = a[ii];
return;
}
[/CODE]




Comments

  • I can't detect anything in your code, but try the following:

    [CODE]
    //reading input:
    for(i = 0; i < 4; i++)
    [red]{ //Try placing these... see if this works [/red]
    for(j = 0; j < 2; j++){
    fin >> boxes[i][j].w;
    fin >> boxes[i][j].h;
    boxes[i][j].state = 0;//normal state.
    }
    [red]}[/red]
    [/code]
    Best Regards,
    Richard

  • in the rot function, idx counts to 8, but is used to index an array of length 4.

    You should really use more brackets. I would imagine that you want your thrid for loop in the rot function to be inside the big loop (given your indentation), but it isn't.

    You could easily find the bugt yourself if you are working with a good debugger (say Visual Studio): Simply set a breakpoint on "data change" (that the local variable changes its value). You should be able to look in the help section how to do this.

    Hope this helps.

  • : in the rot function, idx counts to 8, but is used to index an array of length 4.
    :
    : You should really use more brackets. I would imagine that you want your thrid for loop in the rot function to be inside the big loop (given your indentation), but it isn't.
    :
    : You could easily find the bugt yourself if you are working with a good debugger (say Visual Studio): Simply set a breakpoint on "data change" (that the local variable changes its value). You should be able to look in the help section how to do this.
    :
    : Hope this helps.
    :
    :
    Thanks, but in my program "int idx" don't go further than 3 {0,1,2,3} the "a" array won't overflow, the bug is not there.

    I mentioned about [RED]j, min_area, w, h[/RED] variables in loop:
    [CODE]
    for (i = 0; i < 3; i++){//possible configs.
    Fill(boxes, i);
    do{
    for([RED]j[/RED] = 0; j < 16; j++){
    [RED]w[/RED] = calcWidth(boxes);
    [RED]h[/RED] = calcHeight(boxes);

    if ([RED]min_area[/RED] > w*h){
    reset_min_area(min_area, w, h);
    }
    else if(min_area == w * h)
    push_to_res(w, h);

    rot(boxes);
    }
    }while (Permutate(boxes));
    }
    [/CODE]

    If you watch those variables during the execution of a this loop, you will notice that their values change after rot() function call.
    It shouldn't happen, because you can't access to variables outside the rot() function, since [RED]j, min_area, w, h[/RED] are not global.
    I asked about this.
  • : I can't detect anything in your code, but try the following:
    :
    : [CODE]
    : //reading input:
    : for(i = 0; i < 4; i++)
    : [red]{ //Try placing these... see if this works [/red]
    : for(j = 0; j < 2; j++){
    : fin >> boxes[i][j].w;
    : fin >> boxes[i][j].h;
    : boxes[i][j].state = 0;//normal state.
    : }
    : [red]}[/red]
    : [/code]
    : Best Regards,
    : Richard
    :
    :
    I mentioned about j, min_area, w, h variables in loop:

    for (i = 0; i < 3; i++){//possible configs.
    Fill(boxes, i);
    do{
    for([RED]j[/RED] = 0; j < 16; j++){
    [RED]w[/RED] = calcWidth(boxes);
    [RED]h[/RED] = calcHeight(boxes);

    if ([RED]min_area[/RED] > w*h){
    reset_min_area(min_area, w, h);
    }
    else if(min_area == w * h)
    push_to_res(w, h);

    rot(boxes);
    }
    }while (Permutate(boxes));
    }

    If you watch those variables during the execution of a this loop, you will notice that their values change after rot() function call.
    It shouldn't happen, because you can't access to variables outside the rot() function, since j, min_area, w, h are not global.
    I asked about this.


  • [b][red]This message was edited by MT2002 at 2007-1-31 23:54:32[/red][/b][hr]
    [code]
    //processing ( the main part ):
    for (i = 0; i < 3; i++){//possible configs.
    Fill(boxes, i);[b]
    do{[/b]
    for(j = 0; j < 16; j++){//loop with a bug.
    w = calcWidth(boxes);
    h = calcHeight(boxes);

    if (min_area > w*h){
    reset_min_area(min_area, w, h);
    }
    else if(min_area == w * h)
    push_to_res(w, h);

    rot(boxes);//the strange thing occurs in this loop
    [b]}
    }while (Permutate(boxes));[/b]
    }
    [/code][blue]
    [b]int j[/b] is being assigned [b]null(0)[/b] each time it enters the inner loop. The inner loop is housed in a do-while loop. [b]If the while() condition is not met, execution jumps back up before the loop, so the loop starts again (resetting j to 0)[/b] This is also true to [b]w[/b] and [b]h[/b]. Because [b]w[/b] and [b]h[/b] are used in calculations, they may jump to unexpected values (Though the calculations are technically correct)

    Also, this will also conclude why min_area is being reset (The call to reset_min_area() )

    These varables are updating correctly. I suspect this is what you are referring to. (Check ran through debugger)

    On a side note, I do have two suggestions...

    -[b]Always initialize varables as soon as they are declared[/b]

    -Try to give the varables more meaningful names. ii and ij do not describe what the varabe is for.

    Hope this helps;
    [/blue]








  • : Hi everyone.
    : I've got a really awful bug in my program.
    : The problem is a variable ('int j '), which controls the number of loops to be made. It changes unexpectedly, although there is nothing that can change it.If you could have a glance at my code (this strange thing occurs at line #74, after a rot(boxes); function call) this won't take much time for professional programmers..
    : In addition, i tried to change the variable by declaring another one with different name, but it didn't work. No functions that I use in that loop mustn't change the value of that variable.But they change in some way! The variables j, w, h, min_area change after the rot(boxes) function call. Maybe there is something wrong(I used pointers there)?

    When a local variable changes when it "shouldn't," it almost always means that a function has overflowed a local buffer somewhere. In this case the problem is in the rot() function. Look carefully at how the variable 'idx' is used in that function.

    Don't be so surprised by things like this. This problem rates about 1 out of 10 on the mysterious scale.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories