Common reasons for bugs in release version not present in debug mode
Many times, in debug mode in C++ all variables are null initialized, whereas the same does not happen in release mode unless explicitly stated.
Check for any debug macros and uninitialized variables
Does your program uses threading, then optimization can also cause some issues in release mode.
Also check for all exceptions, for example not directly related to release mode but sometime we just ignore some critical exceptions, like mem access violation in VC++, but the same can be a issue at least in other OS like Linux, Solaris. Ideally your program should not catch such critical exceptions like accessing a NULL pointer.
Bugs in Release not in Debug
One common glitch when switching is the behavior of uninitialized variables. Do you ever set all of the uicGrids[][] to some initial value?
Frequently, Debug will automagically initialize these to 0 for you.. Release leaves them with whatever ram is leftover from previous usage.
bug on RELEASE but not on DEBUG
The %s
format specifier expects a NULL terminated char*
. You are passing in a std::string
instance. If it works in DEBUG, that's just pure luck.
You should use:
std::string s("foo");
sprintf(buf, "%s", s.c_str());
This will extract a char*
and ensure that the buffer is NULL terminated.
It is possible that in the runtime library std::string
has different implementations for DEBUG and RELEASE. Try compiling using both settings, but adding debug symbols to the RELEASE build and then step through the code. Look at the memory location where s
is stored. Is there any difference?
A bug that is not present in debug mode, but just when i run the project
Thanks for the MCVE. Without it, it would have been impossible to find out what was wrong, because the problems are in parts of the code you did not show.
The problem starts with the fact that the user base class Utente extends GregorianCalendar
. A user is not a calendar. Maybe a user has or uses one or more calendars. If your class is about OOP principles, you may want to study the differences between generalisation (inheritance) vs. composition vs. aggregation vs. association.
The rather technical problem with Utente
extending GregorianCalendar
is that its parent class Calendar
already implements Comparable<Calendar>
. So if you want to override compareTo
, you cannot just override compareTo(Object)
like you tried (but commented out), or even compareTo(Studente)
in order to achieve sorting in a TreeSet
, but you need to override compareTo(Calendar)
. The other two variants will never be called.
Background: Due to type erasure, You cannot implement the same interface twice for different generic types, i.e. something like Studente extends Utente implements Comparable<Studente>
will yield a compile error "java.lang.Comparable cannot be inherited with different arguments: <scuola.Studente> and <java.util.Calendar>"
.
The consequence of the above is that, the way your code looks now on GitHub, your TreeSet<Studente>
will be sorted as a set of Calendar
objects. But Utente
does not initialise the parent calendar instance by calling super(...)
in its own constructors, i.e. the calendar will be uninitialised, because only its default constructor with no arguments will be called. But that one is inherited by Object
and not overridden by any calendar or user class, i.e. Calendar.compareTo
, when noticing that no time is set for itself, will simply always use System.currentTimeMillis()
. The results are hard to predict and seem non-deterministic, even though of course they are perfectly deterministic, but dependent on when compareTo
is called for which Studente
object, and which ones are on the left and right hand sides of the comparison.
Therefore, because Calendar.compareTo(Calendar)
is inadequate for class Studente
, the TreeSet
will have inconsistent sorting and e.g. A < B and B < C does not reliably mean A < C. It could even be that you get A < B one time and B < A at the same time. Your TreeSet
, if you simply print its size or print its toString()
value to the console, will show the correct size and the correct set of Studente
elements. But when iterating over it like you do in the Classe.toString()
method, you will see strange results due to the bogus ordering, because it upsets the set iterator. By the way, I would recommend a toString
method printing only a simple string without line breaks. If you want to print something with multiple lines, you should do so in a utility method.
So you have several choices:
Implement
compareTo(Calendar)
inStudente
(maybe also inUtente
, if you need it there). But then you need to make sure that it also does something meaningful for otherCalendar
instances passed in or at least throws meaningful exceptions if something other than aStudent
is passed in. But like I said, a student or user is not a calendar, so this feels awfully wrong.Remove
extends GregorianCalendar
fromUtente
and letStudente implements Comparable<Studente>
instead. Then implement acompareTo(Studente)
method which is consistent withequals(Object)
. Because yourequals
method compares first by ID (matricola
), then by last name (cognome
) and first name (nome
), you should do the same incompareTo
and not use some other criterion likemediaVoti()
there. If you want to sort by average votes (whatever that means in your context), you can still do so later usingCollections.sort(List, Comparator)
or so, using a custom comparator.Do not implement
Comparable
at all, use a normal, unsorted set and sort students on demand usingCollections.sort(List, Comparator)
.
I am showing you no. 2, so you can learn something about Comparable
and compareTo
:
public class Utente /*extends GregorianCalendar*/ {
// ...
}
public class Studente extends Utente implements Comparable<Studente> {
// ...
/**
* Confronta per matricola, cognome, nome
*/
@Override
public int compareTo(Studente altroStudente) {
if (this.equals(altroStudente))
return 0;
int result = Integer.compare(matricola, altroStudente.matricola);
if (result != 0)
return result;
result = cognome.compareTo(altroStudente.cognome);
if (result != 0)
return result;
return nome.compareTo(altroStudente.nome);
}
// ...
}
This solution also is not perfect, because it will throw exceptions if first or last names are null
. But I guess for your simple solution this is acceptable.
There are many other smaller and bigger problems in your application, but I know you are all just starting, and I think all in all you have achieved a lot together as a group. Just some small things:
Classe.equals(Object)
contains a bug:if (altro == this) return false;
should beif (altro == this) return true;
.PercorsoDidattico.equals(Object)
also contains a problem: When comparing strings, you should useequals
, never==
, i.e. instead ofan.indirizzo == this.indirizzo
you ought to usean.indirizzo.equals(this.indirizzo)
.
I could write more, but the answer is long already.
After fixing the two equals
methods and implementing the Comparable<Studente>
interface correctly, your program prints:
...
input: Matricola: 0, Rossi, Marco Classe 4^B
Iscrizione effettuata: Rossi Marco B 4
Classe 3^A
1: Matricola: 0, Bianchi, Paola
2: Matricola: 0, Rossi, Mario
3: Matricola: 0, Verdi, Luigi
Classe 4^A
1: Matricola: 0, Gialli, Dario
2: Matricola: 0, Neri, Carlo
3: Matricola: 0, Rosa, Rosa
4: Matricola: 0, Rossetto, Giulia
Classe 4^B
1: Matricola: 0, Rossi, Marco
2: Matricola: 0, Viola, Viola
As you can see, the new compareTo(Studente)
method leads to each class being sorted by student last name, then first name, because matricola
is still unused in your program.
Update: By the way, the explanation for why it worked correctly in the debugger or with an additional Thread.sleep()
is probably related to Calendar.compareTo
using different timestamps, which accidentally led to at least the iterator finding all elements in the tree-set. Depending on your code, that would still have failed in other situations, you were just lucky there.
My code works in Debug mode, but not in Release mode
Debug modes often initialize heap data allocations. The program might be dependent on this behavior. Look for variables and buffers that are not getting initialized.
Bug in Release only
You could have uninitialized variables which are automatically initialized by the compiler in debug mode, and not in release mode.
Additionally you could be facing alignment issue and minor memory overruns which you are protected from in debug mode due to having no optimizations but when optimizations are enabled and your code is aligned differently this could cause issues and undefined behavior.
Try making sure that all your variables are explicitly initialized, and not assume that:
int i;
is the same as int i = 0;
How do i know when to use Debug mode or Release mode in flutter?
The apps in debug mode has a bigger size, because load libraries to allow the hot reload and hot restart
In release mode hot reload and hard reload isn't available for the same reason, and recommend use release mode for presentations and depending for some tests
Related Topics
Override Compile Flags for Single Files
How to Use Formatmessage() Properly in C++
C++ Inheritance - Inaccessible Base
How to Return Numpy.Array from Boost::Python
What Is the Scope of a 'While' and 'For' Loop
Vector That Can Have 3 Different Data Types C++
Ncurses and Qt Interoperability
Function Declaration Inside or Outside the Class
How to Determine the Size of an Object in C++
Cmake Unable to Determine Linker Language with C++
Where Are C/C++ Main Function's Parameters
Inferring the Call Signature of a Lambda or Arbitrary Callable for "Make_Function"
How to Return a Char Array from a Function