Programming and cultivation (3)

zhaozj2021-02-08  221

6, the IF statement to the error process ----------- I saw you said, this is good to say. Still first look at a program code.

IF (CH> = '0' && ch <= '9') {/ * Normal processing code * /} else {/ * Output error message * / printf ("error ... / n"); Return False;

This structure is very bad, especially if "normal processing code" is long, it is best not to use ELSE for this situation. Judgment the error first, such as:

IF (CH <'0' || CH> '9') {/ * Output Error message * / printf ("error ... / n"); return (false);} / * Normal processing code * / ...

Is this structure not very clear? Highlight the wrong condition, let others use your function, you can see unhanectation conditions, so you will be more conscious.

7, #ifndef in the header file ---------- Don't ignore the #ifndef in the first part, this is a very critical thing. For example, you have two C files, both C files include the same header file. When compiling, these two C files should be compiled into a run file, so there is a problem, a large number of statements conflicts.

Still put the contents of the header files in #1ndef and #ndif. Whether your header will be referenced by multiple files, you have to add this. The general format is like this:

#ifndef #define ... ...... #ENDIF In theory, it can be freely named, but this "identification" of each header file should be unique of. Named rules identified are generally the header file name, and the line is added to the file, and "" in the file name "also becomes underline, such as: stdio.h

#ifndef _STDIO_H_ #define _stdio_h_ ... #ENDIF (BTW: More useful features for precompilation. Will you use pre-compiled?)

8, allocate memory on the pile --------- Many people may not understand the "stack stack" and "stack of HEAP" on memory allocation. People who include some barborses are not understanding these two concepts. I don't want to say more about these two things. Simply put, the memory system allocated on the Stack is automatically released, the memory allocated on the HEAP is not released, even if the program exits, the memory is still there. Stack is typically static allocation of memory, and HEAP is generally dynamically allocated.

The memory allocated by the Malloc system is allocated from the heap. The memory allocated from the pile must be released by himself. Use free release, or the term - "Memory Leak" (or "Memory Vulnerability") - Memory Leak. Thus, the system's allocated memory will be less and less Mallo, until the system crashes. Let's take a look at the difference between "stack memory" and "stack memory".

Stack memory allocation ----- char * allocstrfromstack () {char pstr [100]; return pstr;} 内 分 ----- char * allocstrfromheap (int LEN) {char * pstr; if (len <= 0 Return Null; Return (Char *) Malloc (LEN);} For the first function, the internal presence of the PSTR is released when the function returns. So the return of the char * is nothing. For the second function, it is allocated from the heap, so even if the program is exited, it is not released, so the memory returned by the second function is no problem, which can be used. But must call free release, otherwise Memory Leak!

The distribution of memory is easy to cause memory leaks, which is the largest "gith" of C / C . If your program is stable, then Do not appear Memory Leak. So, I still have to pay a thousands of people here, be careful when using the Malloc system function (including Calloc, Realloc).

Remember to have a service application on UNIX, there are a few hundred C files compiled, run a good test, etc., the system is Down every three months, and many people can't find the problem. . I have to manually restart the system every two months. This problem is that MeMery Leak is strange, and this problem in C / C will always happen, so you must be careful. A Rational's Detection Work - Purify, you can help you test your programs do not have memory leaks.

I promise that the programmer of many C / C projects will have some cold in Malloc or New. When you use Malloc and New, there is a light tight and fearful feeling, you have this kind of cultivation. For Malloc and Free operations have the following rules:

1) Pairing, there is a malloc, there should be a free. (C corresponds to new and delete) 2) Try to use on the same layer, do not like the above, Malloc in the function, and free outside the function. It is best to use these two functions on the same call layer. 3) Malloc allocated memory must initialize. The pointer behind free must be set to NULL.

Note: Although the current operating system (such as Unix and Win2K / NT) have process memory tracking mechanism, that is, if you have released memory, the operating system will help you release it. However, the operating system still does not release all the memory of Memory Leak in your program, so it is best to do this work. (Sometimes I don't know anything, there is a Memory Leak, and I find a non-sea cut pin in the code of millions of rows. Rational has a tool called Purify, which may be good to check the Memory Leak in the program.

9, the initialization of the variable -------- Joined the above, the variable must be initialized and reused. The C / C compiler will not help you initialize like Java, all need you, if you use no initialized variables, the result is unknown. Good programmers have never initialized the variables before using variables. Such as: 1) MemSet clear operation is performed on the memory allocated by Malloc. (You can use the Calloc assigning a total memory) 2) Initialize the Struct or array assigned on some stacks. (It is best to clearly), but also said that it is back, initialization will also cause a certain overhead of the system running time, so don't initialize all variables, this is meaningless. A good programmer knows which variables need to be initialized, which is not required. Such as: The following situations are not required. Char * pstr; / * A string * / pstr = (char *) Malloc (50); if (pstr == null) exit (0); strcpy (pstr, "hello qld");

But if it is the case, it is best to perform memory initialization. (The pointer is a dangerous thing, must initialize)

Char ** PSTR; / * A string array * / pstr = (char **) Malloc (50 * sizeof (char *)); if (pstr == null) exit (0); / * Make pointers in arrays Both point to null * / memset (pstr, 0, 50 * sizeof (char *)); and for global variables, and static variables, it must be initialized when declaring. Because you don't know where it will be used for the first time. So the initial use before use is more unrealistic, so you must initialize them when declaring. Such as:

LINKS * PLNK = NULL; / * For global variables, PLNK is initialized to null * /

10, how to use H and C files --------- H files and C files? In general, the H file is a Declare, which is define in the C file. Because the C file should be compiled into the library file (Windows is .Obj / .lib, UNIX is .o / .a), if others want to use your function, then reference your H file, so h file Generally, variables, macro definitions, enumeration, structures, and function interfaces, just like an interface description file. The C file is a detail.

The maximum use of H files and C files is declaration and implementation. This feature should be recognized, but I still see some people like to write the function in the H file, this habit is very bad. (If it is C , for its template function, only the implementation and declarations in the VC are written in a file because the VC does not support the export keyword). Moreover, if the implementation of the function is written in the H file, you have to add the dependency of the header file in makefile, which will make your makefile unregistered.

Finally, there is a place that is most important to pay attention to: the global variable with initialization should not be put in the H file!

For example, there is a structure that handles error messages:

Char * errmsg [] = {/ * 0 * / "no error", / * 1 * / "open file error", / * 2 * / "failed in sending / receiving a message", / * 3 * / "BAD Arguments ", / * 4 * /" Memeroy Is Not Enough ", / * 5 * /" Service is Down; Try Later ", / * 6 * /" Unknow Information ", / * 7 * /" a socket Operation Has Failed ", / * 8 * /" permission denied ", / * 9 * /" bad configuration file format ", / * 10 * /" communication time out ", ... ......}; Don't put this thing in the header file, because if your header is used by 5 function libraries (.lib or .a), he is linked in these 5 .lib or .a, and If your program uses a function in these five functions libraries, and these functions have been used in an array of error information. Then this information will have 5 copies existing in your executter. If your Errmsg is big, and your execution file will become bigger. The correct way to write it into the C file, and then add external declaration on each of the Errmsg's C file headers, let the compiler will take him when the compiler is in the link. Come, there will only be an errmsg exists in the execution file, and so that this is good to package.

The most crazy thing I have encountered is that in my target file, this errmsg has a total of 112 copies, and the execution file is about 8m. When I put errmsg in the C file, and after more than a thousand C files with Extern declaration, all the function library files decreased by about 20%, and my executive file was only 5m. There is a little less than 3m.

[Note] ----- There is a friend to tell me, this is just a special case, because if errmsg exists in the execution file, speed up the program running speed, the reason is that the multiple copies of errmsg will make the system The memory change is reduced and the efficiency is improved. There is only one errmsg we mentioned here. When a function is to use Errmsg, if the memory is far apart, it will generate a change, but the efficiency is not high.

This statement is not reasonable, but in general, for a relatively large system, errmsg is relatively large, so that the copy caused the size of the execution file to become large, not only adding the system loading time, but also a program in memory More page. For ERRMSG such data, in general, it will not be used frequently when the system is running, so the memory switching is not frequent. Under the trade-off, there is only one efficiency of Errmsg. Even if it is used frequently like LogMSG, the operating system's memory scheduled algorithm will allow such frequently used pages to be stored, so there will be no memory change issues. <- Previous Next->

(All rights reserved, please indicate the source and author information when reproduced)

转载请注明原文地址:https://www.9cbs.com/read-1116.html

New Post(0)