When we use C ++ multithreading for testing, there are many points worth attention. In this article, we will summarize several important precautions and hope to help you fully master the C ++ multi-threaded testing methods.
- How can C ++ inline functions help us?
- C ++ smart pointer Application Experience
- What is C ++ hosting?
- C ++ command line mode compilation and setting skills
- Introduction to using C ++ to define variables
In the last post, I talked about the cross-platform problem of C ++ multithreading. Later, I felt like I was not doing anything. Today, some precautions for debugging and testing when developing C ++ multi-threaded applications. The following precautions are mainly for C ++, but some are also applicable to other languages.
★About breakpoint setting and one-step execution
Many people rely heavily on the breakpoint and single-step functions of the debugger. This is fine in the case of a single thread, but some single-threaded but GUI-related programs will also be a little troublesome ). As for multi-threaded program debugging, these two methods are the beginning of a nightmare. Most of the main problems caused by multithreading are related to Race Condition. For more information, see "here. However, setting a breakpoint or one-step tracking may seriously affect the competition among multiple threads. What you see is an illusion. For example, there are two threads for concurrent execution, and some discord bugs are caused by competition ). Once you set a breakpoint in a thread, the thread stops at the breakpoint, and only the other thread is running. At this time, the concurrency scenario has been completely destroyed, and you may see a harmonious scenario through the debugger.
Run the question a little. This is similar to the "Uncertainty Principle" of Quantum Mechanics. The observer's observation behavior interferes with the object to be measured, causing the observer to see an interference phenomenon.
★About Log output
Since breakpoint and single step are not easy to use. What should I do? An alternative solution is to output log. It can effectively reduce the side effects caused by breakpoints and individual steps on race conditions.
◇ Traditional Log mechanism problems
The traditional log output is mainly printed to the screen or to the file. For C ++, the built-in classes and functions of the standard library, such as cout, printf, and fputs, may have thread security issues related to the specific implementation of the compiler ). In particular, the eight global objects of the standard stream library iostream must be used with caution. If it is light, the output log text is mixed. If it is heavy, the program crashes.
For the above reasons, we should try to use the log mechanism built in the third-party thread library to handle the log output function. For example, ACE's built-in ACE_Log_Msg.
◇ Log functions must be short and concise
In many cases in C ++ multi-threaded testing, we wrap a common function to implement the log output function. Then, the function calls the log class/function of the thread library. In order not to affect the Race Condition of the thread, this log function should be as simple as possible: do not involve too many trivial matters, do not perform time-consuming operations, and try not to operate some global variables.
◇ Log side effects
However, even if the log function is short and concise, it may affect the race condition. After all, log also has overhead and also consumes CPU time ).
In case the race condition is affected by the log, it will be tricky. I have encountered this kind of situation before: Adding log, the program is normal; removing log, the program crashes randomly. In this case, there are two possible reasons: either the log function is faulty, or the program's race condition is very sensitive, and the log overhead will be affected ).
At this time, you can only rely on the naked eye and the human brain. First, let's take a closer look at the relevant Code and documentation several times. We 'd better find other experienced people to Review the Code together.
★About the Debug and Release versions
C ++ programs often have different versions of Debug and Release. In some cases, this may also lead to multithreading issues.
The Debug version contains debugging information and some debugging mechanisms, such as assert macros, are enabled ). Therefore, the competition for multithreading may be affected. In bad luck, the Debug version works normally, and the Release version program crashes randomly. To avoid this situation, consider the following two methods:
◇ Discard the Debug version
You can simply discard the Debug version. In this case, you need to consider replacing debugging-related macros such as assert with your own set of macros so that they can take effect in non-Debug Versions.
◇ Two versions of synchronous C ++ multithreading Test
With this method, programmers can use the Debug version for self-testing, but testers must use the Release version for routine testing. The specific operation steps can be used to assist in daily building. For details, refer to "Here "). Be sure to avoid: In normal times, only Debug version testing will be performed, and the Release version will be created on the eve of the Release. This is very dangerous!
★Machine Hardware for C ++ multi-thread testing)
It's a personal experience and impressive thing.
When ACE was used to develop cross-platform programs, the company's development and testing environments were single-CPU machines. At that time, the multi-core machine was not available, and the multi-CPU machine was expensive, and the company was not willing to spend money on configuration.
After the software is developed, the tester has gone through several rounds of regression tests and has not found any major problems. However, running in the customer's environment often causes random crashes. Because debugging cannot be performed in the customer environment, and the Environment is okay, several developers in the development team have to give full play to the functions of the human eye and human brain and stare at the code and design documents ). After N for a long time, I almost broke my head and realized that the customer's machine was multi-CPU. Then I quickly borrowed a multi-CPU machine from other departments, installed the software for debugging, and finally found out there was a problem with a third-party library. After that, I immediately came up with various methods to apply for multiple CPU machines for testing.
I strongly recommend that you configure multi-core/multi-CPU machines for every programmer and tester if you are developing multi-threaded applications. After all, now multi-core machines are very popular, even if multiple CPU machines, the price is still reasonable. There is no need to introduce development risks to save that small amount of money. This will not only waste time on developers/testers, but also increase implementation and maintenance costs ).
In addition, some may ask "How to compress hyper-threading machines ?" If you are interested in the differences among multiple CPUs, multiple cores, and hyper-threading, you can refer to "here ". I personally feel that hyper-threading is not as good as multi-core and multi-CPU.
The above is an introduction to the C ++ multithreading test.