终止码
main中返回一个整型值与用该值调用exit是等价的
#include <stdio.h>
main()
{
printf("hello world\n");
}
得到的终止码是随机的,取决于main函数返回时栈和寄存器的内容
yjp@yjp-VirtualBox:~/apue/7environ$ cc hello1.c
hello1.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^
yjp@yjp-VirtualBox:~/apue/7environ$ ./a.out
hello world
yjp@yjp-VirtualBox:~/apue/7environ$ echo $? 打印终止状态
0
yjp@yjp-VirtualBox:~/apue/7environ$ cc -std=c99 hello1.c 启用gcc's 1999 ISO C扩展
hello1.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^
yjp@yjp-VirtualBox:~/apue/7environ$ ./a.out
hello world
yjp@yjp-VirtualBox:~/apue/7environ$ echo $?
0
终止处理程序实例
#include "apue.h"
static void my_exit1(void);
static void my_exit2(void);
int main(void)
{
/*
int atexit(void (*func)(void);
登记终止处理函数,成功返回0
调用函数的顺序与登记的顺序相反
同一函数如若登记多次,也会被调用多次
*/
if(atexit(my_exit2) != 0)
err_sys("can't register my_exit2");
if(atexit(my_exit1) != 0)
err_sys("can't register my_exit1");
if(atexit(my_exit1) != 0)
err_sys("can't register my_exit1");
printf("main is done\n");
return (0);
}
static void my_exit1(void)
{
printf("first exit handler\n");
}
static void my_exit2(void)
{
printf("second exit handler\n");
}
将所有命令行参数送回到标准输出
当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序
#include "apue.h"
int main(int argc, char *argv[])
{
int i;
for(i=0; i<argc; i++)
printf("argv[%d]: %s\n", i, argv[i]);
exit(0);
}
C程序的存储布局空间
正文段。CPU执行的机器指令部分,只读。
初始化数据段。
非初始化数据段。bss段。
栈。
堆。
未初始化的数据段的内容不存放在磁盘上的程序文件中。
size报告正文段、数据段、bss段长度
第4列和第5列分别以十进制和十六进制表示三个段的总长度
共享库
程序第一次执行或第一次第哦也某个库函数时,用动态链接方法将程序与共享库函数相链接
使用共享库可减少可执行文件的长度,但会增加运行时间开销
yjp@yjp-VirtualBox:~/apue/7environ$ cc -static hello1.c 阻止gcc使用共享库
yjp@yjp-VirtualBox:~/apue/7environ$ ls -l a.out
-rwxrwxr-x 1 yjp yjp 912664 5月 20 09:09 a.out
yjp@yjp-VirtualBox:~/apue/7environ$ size a.out
text data bss dec hex filename
823726 7284 6360 837370 cc6fa a.out
yjp@yjp-VirtualBox:~/apue/7environ$ cc hello1.c gcc默认使用共享库
yjp@yjp-VirtualBox:~/apue/7environ$ ls -l a.out
-rwxrwxr-x 1 yjp yjp 8608 5月 20 09:10 a.out
yjp@yjp-VirtualBox:~/apue/7environ$ size a.out
text data bss dec hex filename
1182 552 8 1742 6ce a.out
setjmp和longjmp实例
goto只能在一个函数内部跳转,setjmp和longjmp可在栈上跳过若干调用帧,返回到当前函数调用路径的某一个函数中。
通过此程序说明在调用longjmp后各变量情况。
#include "apue.h"
#include <setjmp.h>
static void f1(int, int, int, int);
static void f2(void);
static jmp_buf jmpbuffer;
static int globval;
int main(void)
{
int autoval; /* 自动变量, 执行longjmp时可能变 */
register int regival; /* 寄存器变量, 执行longjmp时可能变 */
volatile int volaval; /* 执行longjmp时保持不变*/
static int statval; /* 全局或静态变量的值在执行longjmp时保持不变 */
globval = 1;
autoval = 2;
regival = 3;
volaval = 4;
statval = 5;
/*
int setjmp(jmp_buf env);
希望返回到的位置调用setjmp
返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
env: 存放调用longjmp时能用来恢复栈状态的所有信息,全局变量
*/
if(setjmp(jmpbuffer) != 0)
{
printf("after longjmp:\n");
printf("globval = %d, autoval = %d, regival = %d, "
"volaval = %d, statval = %d\n",
globval, autoval, regival, volaval, statval);
exit(0);
}
/* Change variables after setjmp, but before longjmp */
globval = 95;
autoval = 96;
regival = 97;
volaval = 98;
statval = 99;
f1(autoval, regival, volaval, statval); /* never returns */
exit(0);
}
static void f1(int i, int j, int k, int l)
{
printf("in f1():\n");
printf("globval = %d, autoval = %d, regival = %d, "
"volaval = %d, statval = %d\n",
globval, i, j, k, l);
f2();
}
static void f2(void)
{
/*
void longjmp(jmp_buf env, int val);
env: 在调用setjmp时所用的env
val: 作为从setjmp处返回的值。setjmp可根据此值,判断造成返回的longjmp在哪里调用
*/
longjmp(jmpbuffer, 1);
}
不带任何优化的编译:
打印当前资源限制
#include "apue.h"
#if defined(BSD) || defined(MACOS)
#include <sys/time.h>
#define FMT "%10lld "
#else
#define FMT "%10ld "
#endif
#include <sys/resource.h>
/*
ISO C的字符串创建运算符#,可为每个资源名产生字符串值。
如 doit(RLIMIT_CORE); 将由C预处理程序扩展为:
pr_limits("RLIMIT_CORE", RLIMIT_CORE);
*/
#define doit(name) pr_limits(#name, name)
static void pr_limits(char *, int);
int main(void)
{
#ifdef RLIMIT_AS
doit(RLIMIT_AS);
#endif
doit(RLIMIT_CORE);
doit(RLIMIT_CPU);
doit(RLIMIT_DATA);
doit(RLIMIT_FSIZE);
#ifdef RLIMIT_LOCKS
doit(RLIMIT_LOCKS);
#endif
#ifdef RLIMIT_MEMLOCK
doit(RLIMIT_MEMLOCK);
#endif
#ifdef RLIMIT_NOFILE
doit(RLIMIT_NOFILE);
#endif
#ifdef RLIMIT_RSS
doit(RLIMIT_RSS);
#endif
#ifdef RLIMIT_SBSIZE
doit(RLIMIT_SBSIZE);
#endif
#ifdef RLIMIT_STACK
doit(RLIMIT_STACK);
#endif
#ifdef RLIMIT_VMEM
doit(RLIMIT_VMEM);
#endif
exit(0);
}
static void pr_limits(char *name, int resource)
{
/*
struct rlimit
{
rlim_t rlim_cur; soft limit: current limit
rlim_t rlim_max; hard limit: maximum value for rlim_cur
}
*/
struct rlimit limit;
/*
int getrlimit(int resource, struct rlimit *rlptr);
查询资源限制
int setrlimit(int resource, const struct rlimit *rlptr);
更改资源限制
*/
if(getrlimit(resource, &limit) < 0)
err_sys("getrlimit error for %s", name);
printf("%-14s ", name);
if(limit.rlim_cur == RLIM_INFINITY)
printf("(infinite) ");
else
printf(FMT, limit.rlim_cur);
if(limit.rlim_max == RLIM_INFINITY)
printf("(infinite) ");
else
printf(FMT, limit.rlim_max);
putchar((int)'\n');
}