C++ Code Different Behavior Under Different OS

Pages: 12
Hello, I would like to ask if someone could help me with a problem that I have with my c++ code for a project I am implementing.
I am currently implementing Reed solomon Decoding for QR Codes and I have gone a lot way by now. The project is built under Visual Studio in Windows OS, But when I am trying to run it under GNU/Linux OS , after a point in my code I get no accepted/correct results. So, the problem is that I am tied working only under VS under Windows, cause under Linux I can not continue my project correctly. So, I am suspecting that this is a native problem between the two compilers that are used, Microsoft Visual Studio Compiler and GCC under Linux. I am also suspecting that the next line is the point that everything is getting wrong ::
S[i] = ( !ret_a_power(rx[idx]) ) ? 0 : ret_integer( ( ret_a_power(rx[idx]) + (i*j) )%255 );

So, how can modulo drives my code to that kind of misbehaviors and wrong results ??

Could anyone of you people tell me an opinion about correcting this major problem or at least what could the problem be ??

Thanks for your patience ...
Last edited on
Write some quick code to see if char is signed or unsigned on each compiler. That could cause a lot of trouble. Another possibility is that your memory management is off. This could cause different behavior on different OSs, or even when slightly changing the code.

Add code to print or log the value of S[i] after the statement you showed in your post. You might find that the problem isn't there.
The problem is definitely there but I do not know why modulo causes these kind of problems, so I am unable using Linux.
@diman91

Please could you put the lines
1
2
3
4
cout << "i = " << i << "   j = " << j << "   idx = " << idx << endl;
cout << "rx = " << rx[idx] << endl;
cout << "ret_a_power = " << ret_a_power(rx[idx]) << endl;
cout << "ret_integer = " << ret_integer(   ( ret_a_power(rx[idx]) + i * j  )%255    ) << endl;


before the line that you think is causing the problem and tell us exactly what your code says (under both Visual Studio and in the linux environment). If they don't run, then put them in one-by-one from the top and tell us which one breaks it. Could you also tell us what the declared size of array rx[] is.

Are you able to share with us the routines ret_a_power() and ret_integer()?

Is there any significance to the fact that you are using %255 (which gives answers in the range 0 - 254) and not %256 (which gives answers in the range 0-255)?

Last edited on
int rx[26];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int rs_forward[256] = {1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,
38,76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,
157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,
35,70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,
95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,
253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,
217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,
62,124,248,237,199,147,59,118,236,197,151,51,102,204,
133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,
154,41,82,164,85,170,73,146,57,114,228,213,183,115,
230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,
227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,
130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,81,162,
89,178,121,242,249,239,195,155,43,86,172,69,138,9,
18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,
176,125,250,233,207,131,27,54,108,216,173,71,142,1};



//256 elements with 1st element 0 || 255 elements with elements as they are in log-antilog table
int rs_reverse[256] = {0,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,224,14,52,141,239,
129,28,193,105,248,200,8,76,113,
    5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,
194,125,106,39,249,185,201,154,9,120,77,228,114,166,
    6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,
148,206,143,150,219,189,241,210,19,92,131,56,70,64,
    30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,
155,159,10,21,121,43,78,212,229,172,115,243,167,87,
    7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,
153,119,38,184,180,124,17,68,146,217,35,32,137,46,
    55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,
211,171,20,42,93,158,132,60,57,83,71,109,65,162,
    31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,
59,82,41,157,85,170,251,96,134,177,187,204,62,90,
    203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,
233,230,231,173,232,116,214,244,234,168,80,88,175};


    

int ret_integer(int a_power)
{
    //Uses forward matrix :
    if(a_power>255) {
        cout << "Error! a's Power > 255!\n";
        exit(1);
    } else {
        return rs_forward[a_power];
    }
}


int ret_a_power(int akeraios)
{
    //Uses reverse matrix :
    if(akeraios>255) { 
        cout << "Error! Integer > 255!\n";
        exit(1);
    } else {
        return rs_reverse[akeraios];   // rs_reverse[akeraios-1] if reverse matrix has 255 elements 
    }
} 



I use %255 cause I work under GF(256), so I need all my values to be inside this field of elements.
Last edited on
@diman91,

Sorry, but could you answer the question precisely and say what your code is giving you for ALL these variables/function evaluations (you MIGHT be implying that idx is 26, but I can't quite tell)
i, j, idx
rx[idx]
ret_a_power(rx[idx])
ret_integer( ( ret_a_power(rx[idx]) + i * j )%255 )


You MIGHT be implying idx is 26 (I can't tell from your answer). If this was the case,
rx[idx] would be 6,
ret_a_power(rx[idx]) would be 26
Your ternary expression would be false, returning the last choice which evaluates as ... I don't know because you still haven't said what i and j are.


Could you:
- tell us what i and j are before the line causing problems;
- tell us what the declared size of array S[] is;
- please do what @dhayden asked and tell us what the value of S[i] is (according to your code) after the line of interest.


I doubt it is the cause of the problem; however, if you are using a Galois field with elements 0,1,2....,255 then please note that taking %255 will only produce elements in the set 0,1,2,...254.


Last edited on
tt = 2 || 4 || 8 || 12 based on a condition
int S[16];

1
2
3
4
5
6
7
8
9
	
for(int i=0;i<tt;i++) {
  idx=0;
  for(int j=25;j>=0;j--) {
    hold = ( !ret_a_power(rx[idx]) ) ? 0 : ret_integer( ( ret_a_power(rx[idx]) + (i*j) )%255 );
    S[i] ^= hold;
    idx++;
  }
}


VS ::
S0=0
S1=0
S2=0
S3=0

GCC :: 
S0=0
S1=1
S2=58
S3=140



http://www.thonky.com/qr-code-tutorial/log-antilog-table
Last edited on
What values do you have in rx?
Hello diman91

I'm struggling to get enough information to generate some compileable code from your various snippets here.

I misread your earlier answer, so I'm still lacking the contents of array rx[]. How is it set?

In your last code snippet you have
S[i] ^= hold;
Is that intentional, or did you mean
S[i] = hold;
They are very different things.


@Peter87 In rx[] I have decimal values.

@lastchance it is S[i] ^= hold. Just at first I didn't wrote hold because I thought it could be something easy someone of you had seen some time in his career about modulo under different compilers.
@diman91

There is nothing wrong with your modulo operation (other than I think it should be %256, not %255).

When you say rx[] contains "decimal values", do you mean floats or doubles? If so, then when you send it to ret_a_power(), which is expecting an integer argument, there is going to be a problem. We still need to know what values are in this array.

If you use a lot of bitwise operations like ^= (or others) there is a possibility that they will behave differently in different implementations if integers are stored in different ways. Another possibility is working beyond array bounds. This won't necessarily crash your system, but, because behaviour is undefined, it could produce different answers on different systems.

If you post code ... please make sure that it is your actual code. In this case it wasn't even functionally equivalent.

Presumably you are coding from some guide formulae or instructions. Is there an internet link to those instructions?
Last edited on
All my operations are done with integer numbers. Also, I have bitwise operations in later stages of the code, but only at that point something goes wrong and under gcc when it makes a bitxor between decimal integer numbers I can see the result is zero, but it should not be zero, because when I am running the exactly same code under VS I have no problem and everything is ok. Last, I do not work over array bounds, that's for sure because otherwise the project would not work properly in VS and I would also had problems there too.
@diman91
In your results a few posts above it is Visual Studio that appears to be giving zero, not gcc: this is exactly the opposite of what you have just written, and rather confusing.

Could you print out the values of S[i] and rx[idx] before the line starting
hold=
and the values of hold and S[i] after the line
S[i]=^hold.
Please do this on both systems. I can't see any other way of working out what is happening on these lines. Note that S[i] needs to have been explicitly initialised before using ^=. If not, that is another thing that could cause differences between systems.
Last edited on
I do not mean S[i]=0, but a value of another variable. S must be zero, and it is in VS, but like I said, under gcc S[i]/=0.

Under gcc ::


Before : 	S[0] = 0
rx[0] = 16
After : 	S[0] = 16
rx[0] = 16
Before : 	S[0] = 16
rx[1] = 140
After : 	S[0] = 156
rx[1] = 140
Before : 	S[0] = 156
rx[2] = 12
After : 	S[0] = 144
rx[2] = 12
Before : 	S[0] = 144
rx[3] = 86
After : 	S[0] = 198
rx[3] = 86
Before : 	S[0] = 198
rx[4] = 106
After : 	S[0] = 172
rx[4] = 106
Before : 	S[0] = 172
rx[5] = 110
After : 	S[0] = 194
rx[5] = 110
Before : 	S[0] = 194
rx[6] = 20
After : 	S[0] = 214
rx[6] = 20
Before : 	S[0] = 214
rx[7] = 234
After : 	S[0] = 60
rx[7] = 234
Before : 	S[0] = 60
rx[8] = 141
After : 	S[0] = 177
rx[8] = 141
Before : 	S[0] = 177
rx[9] = 247
After : 	S[0] = 70
rx[9] = 247
Before : 	S[0] = 70
rx[10] = 161
After : 	S[0] = 231
rx[10] = 161
Before : 	S[0] = 231
rx[11] = 237
After : 	S[0] = 10
rx[11] = 237
Before : 	S[0] = 10
rx[12] = 200
After : 	S[0] = 194
rx[12] = 200
Before : 	S[0] = 194
rx[13] = 197
After : 	S[0] = 7
rx[13] = 197
Before : 	S[0] = 7
rx[14] = 64
After : 	S[0] = 71
rx[14] = 64
Before : 	S[0] = 71
rx[15] = 196
After : 	S[0] = 131
rx[15] = 196
Before : 	S[0] = 131
rx[16] = 131
After : 	S[0] = 0
rx[16] = 0
Before : 	S[0] = 0
rx[17] = 0
After : 	S[0] = 0
rx[17] = 0
Before : 	S[0] = 0
rx[18] = 0
After : 	S[0] = 0
rx[18] = 0
Before : 	S[0] = 0
rx[19] = 0
After : 	S[0] = 0
rx[19] = 0
Before : 	S[0] = 0
rx[20] = 0
After : 	S[0] = 0
rx[20] = 0
Before : 	S[0] = 0
rx[21] = 0
After : 	S[0] = 0
rx[21] = 0
Before : 	S[0] = 0
rx[22] = 0
After : 	S[0] = 0
rx[22] = 0
Before : 	S[0] = 0
rx[23] = 0
After : 	S[0] = 0
rx[23] = 0
Before : 	S[0] = 0
rx[24] = 0
After : 	S[0] = 0
rx[24] = 0
Before : 	S[0] = 0
rx[25] = 0
After : 	S[0] = 0
rx[25] = 0
Before : 	S[1] = 0
rx[0] = 16
After : 	S[1] = 48
rx[0] = 16
Before : 	S[1] = 48
rx[1] = 140
After : 	S[1] = 250
rx[1] = 140
Before : 	S[1] = 250
rx[2] = 12
After : 	S[1] = 255
rx[2] = 12
Before : 	S[1] = 255
rx[3] = 86
After : 	S[1] = 167
rx[3] = 86
Before : 	S[1] = 167
rx[4] = 106
After : 	S[1] = 200
rx[4] = 106
Before : 	S[1] = 200
rx[5] = 110
After : 	S[1] = 155
rx[5] = 110
Before : 	S[1] = 155
rx[6] = 20
After : 	S[1] = 39
rx[6] = 20
Before : 	S[1] = 39
rx[7] = 234
After : 	S[1] = 77
rx[7] = 234
Before : 	S[1] = 77
rx[8] = 141
After : 	S[1] = 180
rx[8] = 141
Before : 	S[1] = 180
rx[9] = 247
After : 	S[1] = 175
rx[9] = 247
Before : 	S[1] = 175
rx[10] = 161
After : 	S[1] = 215
rx[10] = 161
Before : 	S[1] = 215
rx[11] = 237
After : 	S[1] = 139
rx[11] = 237
Before : 	S[1] = 139
rx[12] = 200
After : 	S[1] = 41
rx[12] = 200
Before : 	S[1] = 41
rx[13] = 197
After : 	S[1] = 128
rx[13] = 197
Before : 	S[1] = 128
rx[14] = 64
After : 	S[1] = 24
rx[14] = 64
Before : 	S[1] = 24
rx[15] = 196
After : 	S[1] = 1
rx[15] = 196
Before : 	S[1] = 1
rx[16] = 0
After : 	S[1] = 1
rx[16] = 0
Before : 	S[1] = 1
rx[17] = 1
After : 	S[1] = 1
rx[17] = 1
Before : 	S[1] = 1
rx[18] = 0
After : 	S[1] = 1
rx[18] = 0
Before : 	S[1] = 1
rx[19] = 0
After : 	S[1] = 1
rx[19] = 0
Before : 	S[1] = 1
rx[20] = 0
After : 	S[1] = 1
rx[20] = 0
Before : 	S[1] = 1
rx[21] = 0
After : 	S[1] = 1
rx[21] = 0
Before : 	S[1] = 1
rx[22] = 0
After : 	S[1] = 1
rx[22] = 0
Before : 	S[1] = 1
rx[23] = 0
After : 	S[1] = 1
rx[23] = 0
Before : 	S[1] = 1
rx[24] = 0
After : 	S[1] = 1
rx[24] = 0
Before : 	S[1] = 1
rx[25] = 0
After : 	S[1] = 1
rx[25] = 0
Before : 	S[2] = 0
rx[0] = 16
After : 	S[2] = 80
rx[0] = 16
Before : 	S[2] = 80
rx[1] = 140
After : 	S[2] = 255
rx[1] = 140
Before : 	S[2] = 255
rx[2] = 12
After : 	S[2] = 53
rx[2] = 12
Before : 	S[2] = 53
rx[3] = 86
After : 	S[2] = 40
rx[3] = 86
Before : 	S[2] = 40
rx[4] = 106
After : 	S[2] = 251
rx[4] = 106
Before : 	S[2] = 251
rx[5] = 110
After : 	S[2] = 179
rx[5] = 110
Before : 	S[2] = 179
rx[6] = 20
After : 	S[2] = 108
rx[6] = 20
Before : 	S[2] = 108
rx[7] = 234
After : 	S[2] = 5
rx[7] = 234
Before : 	S[2] = 5
rx[8] = 141
After : 	S[2] = 240
rx[8] = 141
Before : 	S[2] = 240
rx[9] = 247
After : 	S[2] = 202
rx[9] = 247
Before : 	S[2] = 202
rx[10] = 161
After : 	S[2] = 124
rx[10] = 161
Before : 	S[2] = 124
rx[11] = 237
After : 	S[2] = 49
rx[11] = 237
Before : 	S[2] = 49
rx[12] = 200
After : 	S[2] = 187
rx[12] = 200
Before : 	S[2] = 187
rx[13] = 197
After : 	S[2] = 146
rx[13] = 197
Before : 	S[2] = 146
rx[14] = 64
After : 	S[2] = 138
rx[14] = 64
Before : 	S[2] = 138
rx[15] = 196
After : 	S[2] = 106
rx[15] = 196
Before : 	S[2] = 106
rx[16] = 0
After : 	S[2] = 106
rx[16] = 0
Before : 	S[2] = 106
rx[17] = 1
After : 	S[2] = 106
rx[17] = 1
Before : 	S[2] = 106
rx[18] = 106
After : 	S[2] = 58
rx[18] = 58
Before : 	S[2] = 58
rx[19] = 0
After : 	S[2] = 58
rx[19] = 0
Before : 	S[2] = 58
rx[20] = 0
After : 	S[2] = 58
rx[20] = 0
Before : 	S[2] = 58
rx[21] = 0
After : 	S[2] = 58
rx[21] = 0
Before : 	S[2] = 58
rx[22] = 0
After : 	S[2] = 58
rx[22] = 0
Before : 	S[2] = 58
rx[23] = 0
After : 	S[2] = 58
rx[23] = 0
Before : 	S[2] = 58
rx[24] = 0
After : 	S[2] = 58
rx[24] = 0
Before : 	S[2] = 58
rx[25] = 0
After : 	S[2] = 58
rx[25] = 0
Before : 	S[3] = 0
rx[0] = 16
After : 	S[3] = 240
rx[0] = 16
Before : 	S[3] = 240
rx[1] = 140
After : 	S[3] = 134
rx[1] = 140
Before : 	S[3] = 134
rx[2] = 12
After : 	S[3] = 95
rx[2] = 12
Before : 	S[3] = 95
rx[3] = 86
After : 	S[3] = 63
rx[3] = 86
Before : 	S[3] = 63
rx[4] = 106
After : 	S[3] = 183
rx[4] = 106
Before : 	S[3] = 183
rx[5] = 110
After : 	S[3] = 120
rx[5] = 110
Before : 	S[3] = 120
rx[6] = 20
After : 	S[3] = 197
rx[6] = 20
Before : 	S[3] = 197
rx[7] = 234
After : 	S[3] = 219
rx[7] = 234
Before : 	S[3] = 219
rx[8] = 141
After : 	S[3] = 192
rx[8] = 141
Before : 	S[3] = 192
rx[9] = 247
After : 	S[3] = 195
rx[9] = 247
Before : 	S[3] = 195
rx[10] = 161
After : 	S[3] = 19
rx[10] = 161
Before : 	S[3] = 19
rx[11] = 237
After : 	S[3] = 96
rx[11] = 237
Before : 	S[3] = 96
rx[12] = 200
After : 	S[3] = 139
rx[12] = 200
Before : 	S[3] = 139
rx[13] = 197
After : 	S[3] = 248
rx[13] = 197
Before : 	S[3] = 248
rx[14] = 64
After : 	S[3] = 205
rx[14] = 64
Before : 	S[3] = 205
rx[15] = 196
After : 	S[3] = 63
rx[15] = 196
Before : 	S[3] = 63
rx[16] = 0
After : 	S[3] = 63
rx[16] = 0
Before : 	S[3] = 63
rx[17] = 1
After : 	S[3] = 63
rx[17] = 1
Before : 	S[3] = 63
rx[18] = 58
After : 	S[3] = 95
rx[18] = 58
Before : 	S[3] = 95
rx[19] = 95
After : 	S[3] = 140
rx[19] = 140
Before : 	S[3] = 140
rx[20] = 0
After : 	S[3] = 140
rx[20] = 0
Before : 	S[3] = 140
rx[21] = 0
After : 	S[3] = 140
rx[21] = 0
Before : 	S[3] = 140
rx[22] = 0
After : 	S[3] = 140
rx[22] = 0
Before : 	S[3] = 140
rx[23] = 0
After : 	S[3] = 140
rx[23] = 0
Before : 	S[3] = 140
rx[24] = 0
After : 	S[3] = 140
rx[24] = 0
Before : 	S[3] = 140
rx[25] = 0
After : 	S[3] = 140
rx[25] = 0

S[a^0] = 0
S[a^1] = 1
S[a^2] = 58
S[a^3] = 140


Last edited on
Hello @diman91

I think you are saying - please confirm - that:
- for VS, all S[i] are 0 before the call;
- for gcc, all S[i] are in their "Before:" state as above and are not 0. (As a sneaky check you could deliberately reset all S[i] to zero just before your i-loop and see what happens thereafter).

In other words, the differences between the two systems are occurring BEFORE the line that you have drawn attention to.

@Chervil put a useful summary of possible differences up - I hope that he/she will consider reinstating it, but it included:
- uninitialised variables (S[i] would be a prime candidate, but there may be others);
- going beyond array bounds;
- different sizes of chars and ints (particularly if you are doing bitwise operations).

Note that the fact that it doesn't fall down with Visual Studio does NOT mean that any of these don't occur. These are bugs that often creep through specifically because they don't always crash the system. Moreover, they are pretty well bound to produce different answers on significantly different implementations ... and should be taken as an indicator of a bug.

Are you able to try your code on CPP shell? If necessary you may need to bundle multiple files together and use some temporary input to mimic file operations. Turn all warnings to as high a level as possible.


Before the 2 for loops , S[i] are initialized to zero.
I just compiled and run it under https://www.tutorialspoint.com/compile_cpp_online.php
and I get the same results with gcc compiler , it uses the same compiler obviously!
Last edited on
Is int S[16] a local variable? What about int rx[26]?That would explain everything. Local variables are not zero-initialized in C++. They contain whatever the OS and runtime environment happened to leave there.

Before : 	S[0] = 0
rx[0] = 16

How did rx[0] become 16 before you entered this code?

Look, finding problems like this is actually very simple but you have to stop thinking that you know where the problem lies.

Add logging lines like the ones in your previous post to print out all the data before/after the code that's producing the wrong result. Run the code on both systems and see where the data goes bad. Figure out where that data came from and go add logging lines there. Keep working your way back.
@diman91

This is the snippet of code that you posted earlier.
1
2
3
4
5
6
7
8
for(int i=0;i<tt;i++) {
  idx=0;
  for(int j=25;j>=0;j--) {
    hold = ( !ret_a_power(rx[idx]) ) ? 0 : ret_integer( ( ret_a_power(rx[idx]) + (i*j) )%255 );
    S[i] ^= hold;
    idx++;
  }
}


There is nowhere in these nested loops that rx[idx] can change. It doesn't appear on the LHS of anything, nor as a changeable parameter of a function call.

However, if you look VERY carefully in your long list of "Before:" and "After" there are just a few - not many, but a few - occasions when it does. For example, for S[0] = 0, rx[16] quietly goes from 131 to 0. Similarly rx[18] goes from 106 to 58 when S[2] does the same.
Certainly, S[] should change, but I cannot see why rx[] does.

To me, this has all the hallmarks of writing to a memory location beyond your declared array bounds.
int rx[26], S[16]; are global variables.

rx[26] contains decimal int numbers before this function from the execution of another function that fills rx[] matrix;

I will try to find the error. When I find out what causes it I will post here.

Thanks

PS : after what you told me I found out that rx[] matrix was by accident declared as rx[16] the same length as S[16] because of a defined previous constant. So, I guess that VS was intelligent as a compiler and understood that I had made it by accident, so it used the correct length later when I was filling the rx[] matrix with 26 values, BUT gcc could not find by default my mistake and make the rx[] matrix length from 16(mistaken) to 26(correct).
Last edited on
So, I guess that VS was intelligent as a compiler and understood that I had made it by accident

Sorry, @diman91, my experience is that compilers tend to do what they are told to do and make no assumptions about whether coders are having a bad day.

Let us know whether this solves the issue of different results on different systems.

I suggest that you give key arrays the dimension of a named constant (e.g. RXMAX) rather than an easily missable number, like 26, ...or was that 16?


(It has nothing to do with the difference between systems, but I'd still nag you to go and have a chat with your supervisor about the %255 or %256 issue.)
Pages: 12