"C Traps and Defects"----Chapter 5 Library Functions

5.1 The getchar function that returns an integer

Code:

#include<stdio.h>
int main()
{
	char c;
	while((c = getchar())!=EOF)//getchar函数的返回值为整型
		putchar(c);
	return 0;
}

There are three possibilities for the above code:

  1. Some valid input characters are "truncated" so that c has the same value as EOF, and the program will stop halfway through the copy.
  2. It is impossible for c to get the value of EOF, and it falls into an infinite loop.
  3. The program ostensibly works, but it's purely by coincidence. Although the return result of the function geutchar will be "truncated" when it is assigned to the variable c of type char, under many compilers, they do not compare c and EOF in the comparison expression, but compare the return value of the getchar function with EOF! , if the compiler had taken this approach, the above example would have worked fine.

5.2 Update sequence file

When using r+ to write and read files at the same time, use fseek to move the pointer, because the position pointed to by the file pointer changes while writing and reading.

5.3 Buffered output and memory allocation

There are two ways of program output: one is immediate processing; the other is temporarily stored, and then written in large blocks.

setbuf(stdout,buf);

statement will notify the input/output library. All output written to stdout should use buf as the output buffer until the buf buffer is filled or the programmer directly calls fflush (for files opened by write operations, calling fflush will cause the output buffer's contents to be actually written to) into the file), the contents of the buf buffer are actually written to stdout. The size of the buffer is defined by BUFSIZ in the system header file <stdio.h>.

Here is an example:

#include<stdio.h>
int main()
{
	int c;
	char buf[BUFSIZ];
	setbuf(stdout,buf);
	while((c = getchar())!=EOF)
		putchar(c);
}

The above program is wrong because the last time the buf buffer is emptied is after the main() function finishes, as part of the cleanup that the C runtime library has to do before handing control over to the operating system. However, the buf character array has been freed before that.

Two solutions:

  1. static char buf[BUFSIZ];
    
  2. setbuf(stdout,(char*)malloc(BUFSIZ));
    //此处不需要检查malloc函数调用是否成功,因为setbuf函数的第二个参数取值可以为NULL,此时标准输出不需要进行缓冲。
    

5.5 Library functions

The C language implementation includes the signal library function as a way to capture asynchronous time.

#include<signal.h>//需要引用的头文件
signal(signal type , handler function);

The signal type here represents some constants defined in the system header file signal.h, these constants are used to identify the signal type that the signal function will capture. The handler function here is the event handler that will be called when the specified event occurs.

Note: Signals may even appear during the execution of some complex library functions such as malloc. . Therefore, from a safety point of view, signal handlers should not call library functions of the above type.

For example: Suppose the execution of the malloc function is interrupted by a signal. At this point, the data structures that malloc uses to keep track of available memory are likely to be only partially updated. If the signal processing function calls the malloc function again, the result may be that the data structure used by the malloc function is completely collapsed, and the consequences are unimaginable.

Conclusion: Signals are complex and tricky and have some inherently non-portable properties. So we should keep the functions that the signal handles as simple as possible and organize them together so that we can easily modify them when we need to adapt to a new system.

practise

  1. Q: When a program terminates abnormally, the last few lines of program output are often lost, why? What measures can we take to solve this problem?

    A: A program that terminates abnormally may not have a chance to flush its output buffers, so the output generated by the program may be somewhere in memory but never be written out. On some systems, the output data that cannot be written out can be several pages long.

    For programmers debugging such programs, this loss of output is often misleading, as it creates the impression that the moment the program fails is much earlier than it actually does. **The solution is to force the output to not be buffered while debugging. **The solution is as follows:

    setbuf(stdout,(char*)0);
    

    This statement must be executed before any output is written to stdout (including any calls to the printf function). The most appropriate place for this statement is as the first statement of the main function.

  2. The purpose of the following program is to copy its input to its output:

    #include<stdio.h>
    int main()
    {
    	register int c;
    	while((c = getchar())!=EOF)
    		putchar(c);
    	return 0;
    }
    

    Change the code to the following code, the program can still run correctly, but it is much slower, why is this?

    #define EOF -1
    int main()
    {
    	register int c;
    	while((c = getchar())!=EOF)
    		putchar();
    	return 0;
    }
    

    Function calls take longer program execution time, so getchar is often implemented as a macro. This is defined in stdio.h, so a program that does not include the stdio.h header file replaces the getchar macro with a getchar function call wherever the fgetchar macro appears. This program is slow because of the increased overhead caused by function calls. The same rationale applies to putchar.

Guess you like

Origin blog.csdn.net/m0_57304511/article/details/123690989