《APUE》第七章筆記

這一章主要是要解決這麼幾個問題:數組

當執行程序時,main函數是如何被調用的?ide

main函數的原型是:函數

int main(int argc, char *argv[]);佈局

其中argc是命令個數,argv則是字符指針,指向字符串(命令)。spa

當內核執行一個C程序的時候,是由一個特別的起始例程(exex函數族的一個)來調用main函數的。命令行

 

命令行參數是如何傳遞給執行程序的?線程

當執行一個程序時,調用exec的進程可將命令行參數傳遞給該新程序。argc[argc]是NULL。指針

 

典型的存儲器佈局是什麼樣式的?code

一個C程序由這麼幾個segment(段)組成:text segment, data segment, bss segment, stack segment, heap等。對象

bss段就是用來存放全局變量等不在函數內聲明的變量。(因此你定義了一個全局變量,但沒有初始化,你打印出來會是等於0的。由於exec會幫你初始化爲0)

 

如何分配額外的存儲空間?

ISOC指定了三個用於動態分配內存的函數:

(1)malloc,分配指定字節數的存儲區。此存儲區的字節的初始值不肯定。

(2)calloc,爲指定數量和指定字節數的對象分配存儲空間,該空間中的每一位都初始化爲0。

(3)realloc,更改之前分配區的長度(增長或減小),當增長時,則是移向一塊更加的新區域,新增的部分的初始值不肯定。

#include <stdlib.h>

void *malloc(size_t size);

void *calloc(size_t nobj, size_t size);

void *realloc(void *ptr, size_t newsize);

三個函數返回值:成功返回非NULL指針,失敗返回NULL指針

void free(void *ptr);

對於上面的這四個函數,我是對malloc和free比較熟悉。下面再說點,其實實際得到的空間會比要求的會多一些出來,多出來的會用來存儲這個空間的一些參數,好比說:分配空間的大小,指向下一個分配空間的指針等等。

因此使用這些函數通常比較多犯的兩個錯誤是:1.像數組那樣,越界,日後面寫東西,這樣會致使一些很嚴重的錯誤,可能下一個分配空間的指針指向的空間就找不到了。

2.沒有free調那些不用的空間,那麼就會形成泄漏或者free掉一個空指針。

這兩個錯誤都是很難檢測出來的,因此要特別當心。

 

進程如何使用環境變量?

介紹幾個用於環境變量操做的函數:

#include <stdlib.h>

char *getenv(const char *name);

找到則指向該環境變量的指針,不然返回NULL

int putenv(char *str);

int setenv(const char *name, const char *value, int rewrite);

int unsetenv(const char *name);

三個函數返回值:成功返回0,出錯返回非0

getenv()函數就是得到某個環境變量的值;

putenv()取形式爲name = value的,並將其放入環境表中。若是name已經存在,則先刪除原來的定義字符串。

setenv()將name設置爲value。若是環境中name已經存在,則若rewrite非0,則首先刪除現有的定義;若rewrite爲0,則不刪除現有定義(什麼都不幹)。

unsetenv()則刪除name的定義,即便不存在也不出錯。

 

各類不一樣的進程終止方式(由於如今還不太懂,因此也只是簡單的說一下)

有8種方式使進程終止,其中5種是正常終止

1.從main返回

2.調用exit

3.調用_exit或_Exit

4.最後一個線程從其啓動例程返回

5.最後一個線程調用pthread_exit

異常終止有3種方式

6.調用abort

7.接到一個信號並終止

8.最後一個縣城對取消請求做出響應

 

longjmp和setjmp函數以及它們和棧的交互做用

咱們都知道,棧是保存用來保存函數的一些信息的,以便返回時可以找到以前的那個函數。好比這麼一個例子,main函數裏調用do_line函數,do_line函數裏調用cmd_add函數,則當調用到cmd_add函數時,棧是這樣的:

要是在cmd裏遇到錯誤,想返回到main函數時怎麼辦?那就要用到setjmp函數和longjmp函數了。

#include <setjmp.h>

int setjmp(jmp_buf env);

返回值:直接調用返回0,不然就返回longjmp的val值

void longjmp(jmp_buf env, int val);

簡單來講,在嵌套調用的函數中,若是遇到了longjmp函數,則會立刻返回到調用setjmp函數的那個函數。好比說我在cmd_add函中調用了longjmp函數,在main函數中設置setjmp函數。當我在cmd_add函數中由於錯誤而觸發到longjmp函數,那麼就會立刻返回到具備setjmp函數的main函數了。當返回去了,而在棧裏各個函數的變量的值會變得怎樣呢?

下面給出例子:

 1 #include "apue.h"
 2 #include <setjmp.h>
 3 
 4 static void f1(int, int, int, int);
 5 static void f2(void);
 6 
 7 static jmp_buf    jmpbuffer;
 8 static int    globval;
 9 
10 int main(void)
11 {
12     int        autoval;
13     register int    regival;
14     volatile int    volaval;
15     static int    statval;
16 
17     globval = 1;
18     autoval = 2;
19     regival = 3;
20     volaval = 4;
21     statval = 5;
22 
23     if (setjmp(jmpbuffer) != 0)
24     {
25         printf("after longjmp\n");
26         printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d\n",
27                 globval, autoval, regival, volaval, statval);
28         exit(0);
29     }
30 
31     /*
32      * Change variables after setjmp, but before longjmp.
33      */
34     globval = 95;
35     autoval = 96;
36     regival = 97;
37     volaval = 98;
38     statval = 99;
39 
40     f1(autoval, regival, volaval, statval);    /* never return */
41     exit(0);
42 
43 }
44 
45 static void f1(int i, int j, int k, int l)
46 {
47     printf("in f1():\n");
48     printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d\n",
49             globval, i, j, k, l);
50     f2();
51 }
52 
53 static void f2()
54 {
55     longjmp(jmpbuffer, 1);
56 }
View Code

書上說這變量變不變是看狀況,你能夠在你本身的電腦上試一試。

相關文章
相關標籤/搜索