12 key points for compiling portable programs in C/C ++

Source: Internet
Author: User

This article introduces 12 key points for C/C to compile a portable program:
1. Hierarchical Design to isolate the Code related to the platform. Just like testability, portability also needs to begin with design. In general, the top and bottom layers do not have good portability. The top layer is GUI, and most guis are not cross-platform, such as Win32 SDK and MFC. The lowest layer is the operating system API. Most operating system APIs are dedicated.
If the two layers of code are distributed across the entire software, the software's portability will be very poor, which is self-evident. So how can we avoid this situation? Of course, it is a hierarchical design:
The underlying layer uses the Adapter mode to encapsulate APIs of different operating systems into a set of unified interfaces. As for whether to encapsulate the program into a class or a function, it depends on whether you use C or C to write the program sequence. This seems simple, but it doesn't seem as simple as it is (you will understand it after reading the entire article). It will take you a lot of time to write code and test them. It is wise to use existing libraries. There are many such libraries, for example, C library has glib (GNOME basic class), C library has ACE (ADAPTIVE Communication Environment), etc, using these libraries when developing the first platform can greatly reduce the workload of porting.
The top layer adopts the MVC model to separate the interface performance from the internal logic code. Put most of the Code into the internal logic. The interface only displays and receives input. Even if you want to change the GUI, the workload is not great. This is also one of the ways to improve testability. Of course there are other additional benefits. Therefore, even if you use a cross-platform GUI such as QT or GTK to design the software interface, it is very useful to separate the interface performance and internal logic.
If the above two points are achieved, the portability of the program is basically guaranteed, and the other issues are only technical details.

2. Familiarize yourself with the target platforms in advance and reasonably abstract the underlying functions. This is based on the layered design. Most underlying functions, such as threads, synchronization mechanisms, and IPC Mechanisms, correspond to almost one-to-one functions provided by different platforms, encapsulating these functions is very simple, and the work of implementing the Adapter is almost just physical activity. However, for some special applications, the form component itself, take GTK for example. The function based on X Window and the function based on Win32 are very different, in addition to basic concepts such as windows and events, there is almost no difference. If you do not know the features of each platform in advance, you should carefully consider them during design, abstract pumping ports are almost impossible on another platform.

3. Try to use standard C/C functions. Most platforms implement functions specified by POSIX (Portable Operating System Interface). However, these functions provide better performance than Native functions, it is not as convenient as native functions. However, it is best not to use native function functions because they are cheap. Otherwise, the stone will eventually reach its own feet. For example, functions such as fopen are used for file operations, rather than functions such as CreateFile.

4. Try not to use the features in the C/C standard. Not all compilers support these features. For example, VC does not support the macros of variable parameters required in C99, and VC does not fully support some template features. For the sake of security, do not be too radical.

5. Do not use features not explicitly defined in the C/C standard. For example, if you have multiple dynamic databases, each of which has a global object, and the construction of these global objects has dependencies, you will have trouble sooner or later, the order in which these global objects are constructed is not specified in the standard. The operation on one platform is correct. On another platform, it may not be clear that the program will be crashed. In the end, a large number of modifications will be made to the program.

6. Try not to use quasi-standard functions. Some functions are widely used on most platforms, so that everyone regards them as standards, such as atoi (converting strings into integers) and strdup (cloning strings) alloca (allocate automatic memory on the stack) and so on. Don't be afraid of 10 thousand, just in case, unless you understand what you are doing, it is better not to touch them.

7. Pay attention to the details of standard functions. Maybe you don't believe that even a standard function, regardless of internal implementation, is sometimes surprising about its external performance differences. Here are a few examples:
Int accept (int s, struct sockaddr * addr, socklen_t * addrlen); addr/addrlen is originally an output parameter. If it is a C programmer, you are used to initializing all the variables, no problem. If it is a C programmer, it is hard to say. If they are not initialized, the program may be inexplicably crash, and you may not dream about it. This is okay under Win32 and will only happen in Linux.
Int snprintf (char * str, size_t size, const char * format ,......); The second parameter, size, does not include null characters in Win32, and contains null characters in Linux. the difference may take several hours.
Int stat (const char * file_name, struct stat * buf); this function is no problem. The problem lies in the final stat. st_ctime represents the create time in Win32, in Linux, the last modification time is represented.
FILE * fopen (const char * path, const char * mode); there is no problem in reading binary files. Be careful when reading text files. Automatically pre-process the files under Win32. The read content is different from the actual length of the file. in Linux, there is no problem.

8. Be careful with the standard data type. Many people have suffered from the transformation of the int type from 16-bit to 32-bit. This is a long time. Do you know that char is signed on some systems and unsigned On some systems? Do you know that wchar_t is 16 bits in Win32 and 32 bits in Linux? Do you know that there is a signed 1bit bit field. The values are 0 and-1 instead of 0 and 1? These beautiful things, the end of which is a ghost, accidentally with its path.

9. It is best not to use the unique features of the platform. For example, a DLL in Win32 can provide a DllMain function. at a specific time, the Loader of the operating system automatically calls this function. This type of function is very useful, but it is best not to use it. This type of function cannot be guaranteed on the target platform.

10. It is best not to use the unique features of the compiler. Modern compilers are very user-friendly and considerate, and some functions are very convenient to use. For example, in VC, if you want to implement local thread storage, you do not call functions such as TlsGetValue/Tls TlsSetValue. Just add _ declspec (thread) in front of the variable, however, although pthread has similar functions, it cannot be implemented in this way, so it cannot be transplanted to Linux. Gcc also has many extensions, which are not available in VC or other compilers.

11. Pay attention to the features of the platform. For example:
In the DLL under Win32, other functions are invisible to the outside unless explicitly specified as the export function. In Linux, all non-static global variables and functions are externally visible. This should be especially careful. The problems caused by functions of the same name make it difficult for you to check for two days.
Directory separator, '\' in Win32 and '/' in Linux '/'.
Text File line breaks: ''for Win32,'' for Linux, and ''for MacOS ''.
The byte sequence (large-end/small-end) may be different for different hardware platforms.
Bytes alignment. On some platforms (such as x86), bytes are not alignment, which is nothing more than a slower speed. On some platforms (such as arm), it completely reads data in the wrong way, you will not be prompted. If something goes wrong, you may not have a clue at all.

12. It is best to know the resource limits of different platforms. You must remember that the number of files simultaneously opened in DOS is limited to dozens. Today, the operating system is much more powerful, but it is not limited. For example, the default maximum shared memory in Linux is 4 MB. If you limit the common resources on the target platform, it may be of great help and some problems can be easily located.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.