C/C++函数运行有可能会导致错误,我们需要进一步知道错误原因才能有的放矢解决。
C/C++中有两种方式可以获知运行异常时的错误信息:

1
2
3
4
5
6
7
8
#include <stdio.h>
perror(char *)
```

```text
#include <errno.h>
#include <string.h>
errno + strerror(int)

第一种perror(char *)需要引入stdio.h头文件,函数中参数的传入的字符串意思是在打印错误信息时会在错误信息前先打印出所传入字符串参数,便于过滤定位。

第二种需要引入errno.hstring.h头文件,则在程序中可以得到全局有效的errno(error number),errno中记录着上一次函数运行出错时的错误码,该错误码所代表的错误信息可以通过strerror(errno)中打印出来。

许多文章都只说了对于strerror(int)时只include了errno.h。但在gcc编译时,会有个warning:

1
2
3
4
5
6
7
sodino:CLab sodino$ gcc main.c
main.c:19:45: warning: implicitly declaring library function 'strerror' with
type 'char *(int)'
printf("1 errno=%d, desc=%s \n", errno, strerror(errno));
^
main.c:19:45: note: please include the header <string.h> or explicitly provide a
declaration for 'strerror'

warning的信息是说:
库函数strerror()(返回类型是char*,带有一个参数参数类型是int)被隐式的声明了。
建议:includestring.h头文件或精确的声明strerror函数。

提示这个warning的原因是:C语言希望所有的函数都是精确被声明的。strerror是在string.h中声明的函数。而如果一开始没有include string.h,则有可能引起错误。这里被隐式的声明,个人理解是由于使用了printf()该方法是与打印方法相关需要处理字符串,在系统逻辑中会include string.h的缘由。
另搜索到的信息是说C99/C11以后,编译器会将此种做法标明为error,但个人经实践gcc -std=c99 main.c仍是warning。

下来见代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(int argc, const char * argv[]) {
printf("main()start\n");
FILE * filePoint;
filePoint = fopen("/Users/sodino/not_found_404", "r"); // 这一行代码会出错。
filePoint = fopen("/Users/sodino", "r"); // 代码正常

// 打印出上一次函数出错(fopen:404)的信息
// 而不是打印上一个函数fopen(sodino)的运行结果信息
perror("1 perror desc:");
printf("1 errno=%d, desc=%s \n", errno, strerror(errno));

fclose(filePoint); // 正常关闭/Users/sodino文件

return 0;
}

XCode运行结果:

1
2
3
4
main()start
1 perror desc:: No such file or directory
1 errno=2, desc=No such file or directory
Program ended with exit code: 0