So, the problem:
When I run the same C++ code in Visual Studio, with the same input and parameters, I get either the correct output, or an output that is completely messed up (99% of values go to zero).
Now, the code is some very complex, hard to read legacy code that is used for over 20 years and developed by many different people, containing 100k lines of code. I also made some minor changes for one project, that probably caused this unstable behaviour. Not even sure that it's induced by me, but I guess it must be the case. I was thinking of memory issues, maybe because I assigned more elements to some variable that has not that many elements allocated in memory. This normally gives an error, but... . Or might be something else low-level/mid-level, but not sure what.
The problem here is, I have 3 options:
- roll back to a stable version and introduce my changes one by one and test again
- find the root cause in some systematic manner
- Guess and be lucky that I find an error that I'm not even sure what is might look like
The problem, respectively:
- Sometimes the program works well for 20 runs at a time. So, it's gonna take forever to test whilst adding each change one by one and testing each new change... .
- I have no idea how to systematically tackle these kind of issues (I'm not really a programmer, I just have a lot of experience with high level programming like MATLAB, R etc.)
- Luck might not be on my side.
Anyone has any idea how to help with option 2? Like, what kind of issues could possible cause behaviour like that? How can I tackle this, e.g. if it does not work during a run, does it make sense to dig into the code (even thought next run it might work perfectly), should I look at warnings, errors in the output window, etc. ?
*I also have this message in Output-->General:
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.*
I know you don't have all info, but I cannot share my 100k lines of code program here, not,if I would, would you be able to understand much of it without hours of digging. So it's a general question.
Update: when compiling/building the .exe and running, the wrong output does not seem to happen.
Cheers, thanks!
UPDATE: SOLVED, and thanks for the advice!
So, how did I solve it:
- I automated generating lot's of output
- I rolled back until I could find a version that was stable
I already had some things in mind that could cause the error, and this matched with the changes made since the latest stable version. I then deactivated some usual suspects, and the output became stable again. The line I deactivated corrected some wrong input, but only for the product I was working on. I still didn't know exactly why, because the part of the code I deactivated was not directly related to the actual line of error. But somehow it "solved it" (as in, 2 bugs (wrong input for the new product, and one out of bounds memory bug I had created through recent code changes) did actually compensate for each other). But I was close and then I found that from the product I was working on j.m_res_inv[i] went out of bounds, so I created an if to subtract one from the maximum index.
if (b->aidnprdl == FIB_VARIABLE || b->aidnprdl == AGI_VARIABLE)
{
for (int i = 0; i < b->nbre_sc - 1; i++) // don't assign random memory values for a subcontract that does not exist yet ;) and make b->nbre_sc equal the number of actual branche21 subcontracts in the input data
{
b->m_res_inv[i] = j.m_res_inv[i];
b->res_inv_br21 += j.m_res_inv[i];
}
}
else
{
for (int i = 0; i < b->nbre_sc; i++) // original code: b->nbre_sc equals number of branche21 subcontracts
{
b->m_res_inv[i] = j.m_res_inv[i];
b->res_inv_br21 += j.m_res_inv[i];
}
}
What I still don't understand:
- Why does C/C++ not crash when this happens? The random memory location is probably not containing the same variable type (double, int) as needed by j.m_res_inv[i] .
- Even if it works, why does it not put just a random value there?
- Strange thing is, when unstable, every output value (like, an .csv of 2000 rows, 300 columns) would go to zero. This probably depends on particularities of this program but still I would expect one "weird" value not to corrupt each and every computation that in theory, are unrelated to this value (mathematically). Maybe there is some particularity in the program that when somewhere a negative value is encountered it stops computing. Kinda hard to find out was was happening I find.
Anyhow, thanks a lot for all the good advice!
p.s. I marked one answer as definitive, but it's the combination of answers that was useful for me!
b->aidnprdl
is one ofFIB_VARIABLE
orAGI_VARIABLE
, the number of items inb->m_res_inv
(orj.m_res_inv
?) is one less thanb->nbre_sc
, which otherwise seems to be the number of items, deep within the code. Who is supposed to remember this?int upperbound = b->nbre_sc;
, thenif (b->aidnprdl == FIB_VARIABLE || b->aidnprdl == AGI_VARIABLE) upperbound--
and finallyfor (int i = 0; i < upperbound; i++)
? Or even better: why ism_res_inv
not astd::vector
, so it knows it's correct size?