99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何對(duì)NULL指針地址建立合法映射,從而合法訪(fǎng)問(wèn)NULL指針

Linux閱碼場(chǎng) ? 來(lái)源:Linuxer ? 2019-11-29 14:26 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本文將介紹如何對(duì)NULL指針地址建立合法映射,從而合法訪(fǎng)問(wèn)NULL指針。本文表達(dá)的宗旨:

任何虛擬地址,只要有合法的頁(yè)表映射,就能訪(fǎng)問(wèn)!

提到C語(yǔ)言編程,我想幾乎所有人都遭遇過(guò)NULL指針。我們的代碼中總是在不斷的判斷指針是否為NULL:

if (p1 != NULL) {

//...

}

if (p2 == NULL) {

exit(-1);

}

如果我們忘記了這種判斷,我們會(huì)收獲到段錯(cuò)誤:

[15445.731305] a.out[3511]: segfault at 0 ip 000000000040071c sp 00007ffedbacbdd0 error 4 in a.out[400000+1000]

誠(chéng)然,我們都討厭segfault,但segfault并非由于訪(fǎng)問(wèn)NULL指針引起的,相反,我們要感謝NULL指針,它幫助我們的程序排除了大量的segfault。

在現(xiàn)代操作系統(tǒng)中,程序訪(fǎng)問(wèn)的地址都是虛擬地址,硬件MMU結(jié)合操作系統(tǒng)創(chuàng)建的頁(yè)表會(huì)在進(jìn)程私有虛擬地址和全局物理地址之間做映射,當(dāng)程序訪(fǎng)問(wèn)一個(gè)虛擬地址的時(shí)候,該映射會(huì)將這次訪(fǎng)問(wèn)轉(zhuǎn)換成到物理地址的訪(fǎng)問(wèn)。

所以,segfault的本質(zhì)是程序訪(fǎng)問(wèn)的虛擬內(nèi)存地址無(wú)法合理映射到物理地址的一種錯(cuò)誤通知。

引發(fā)segfault的地址成為非法地址。

現(xiàn)在,隨意給出兩個(gè)虛擬地址:

unsigned char *p1 = 0x7f1233443344;

unsigned char *p2 = 0xaa12bb443344;

誰(shuí)能說(shuō)出哪個(gè)虛擬地址是合法的,哪個(gè)是非法的?誰(shuí)也說(shuō)不出,只有試著訪(fǎng)問(wèn)它的時(shí)候才知道,引發(fā)segfault的地址就是非法的,否則就是合法的。這可能會(huì)對(duì)程序數(shù)據(jù)造成嚴(yán)重的傷害。

因此有必要人為規(guī)定一個(gè)非法地址,這樣在程序中就可以做判斷了,只要不是人為規(guī)定的那個(gè)非法地址,那就是合法的。至于說(shuō)誰(shuí)來(lái)嚴(yán)格保證其合法性,除了需要編程規(guī)范和編程習(xí)慣之外,操作系統(tǒng)也確實(shí)不會(huì)為該非法地址映射可以訪(fǎng)問(wèn)的物理頁(yè)面。有法可依只是安全的必要條件,加上違法必究才是充分且必要的。

數(shù)字0是最特殊的,判斷一個(gè)值是否為0在硬件層面上也很高效,把0作為非法地址具有高度的可辨識(shí)性,于是幾乎所有的編程語(yǔ)言都用0來(lái)表示非法地址:

#define NULL 0

這就是NULL指針的本質(zhì)。

現(xiàn)在讓我們忘掉編程層面的原則,重新審視NULL指針。

NULL指針指示地址0,地址0沒(méi)有什么特殊的,它就是進(jìn)程地址空間的一個(gè)普通地址,只要為其映射一個(gè)可以訪(fǎng)問(wèn)的物理地址,它就是可以訪(fǎng)問(wèn)的。下面我們就來(lái)試試。

首先我們寫(xiě)個(gè)簡(jiǎn)單的C程序:

// gcc access0.c -o access0

#include

#include

#include

int main(int argc, char **argv)

{

int i, j;

unsigned char *nilp = NULL;

unsigned char *used = NULL;

used = (unsigned char *)calloc(128, 1);

// 寫(xiě)頁(yè)面,調(diào)物理頁(yè)面到內(nèi)存。

strcpy(used, "zhejiang wenzhou pixie shi");

// 以下的打印便于將信息傳遞到內(nèi)核模塊,這只是為了方便,真正

// 正確的做法應(yīng)該自己去hack這些信息,然后傳遞到內(nèi)核模塊。

printf("pid=%d addr=%p ", getpid(), used);

// 等待內(nèi)核模塊創(chuàng)建NULL地址的頁(yè)表,完成后敲回車(chē)。

getchar();

// 打印NULL指針的前64個(gè)字節(jié)

for (i = 0; i < 4; i++) {

for (j = 0; j < 16; j++) {

printf("0x%0.2x ", *nilp);

nilp++;

}

printf(" ");

}

getchar();

free (used);

return 0;

}

可以看到,從for循環(huán)開(kāi)始,我們的程序訪(fǎng)問(wèn)NULL指針地址后的64字節(jié)的數(shù)據(jù)。我們希望把NULL指針映射到calloc的地址處,然后看看是不是打印出了 “zhejiang wenzhou pixie shi”。

這個(gè)很簡(jiǎn)單,寫(xiě)一個(gè)內(nèi)核模塊,把NULL開(kāi)始的一個(gè)page和calloc返回的used開(kāi)始的一個(gè)page映射到同一個(gè)物理頁(yè)面即可。

下面該寫(xiě)內(nèi)核模塊了,為了簡(jiǎn)化操作,這里采用Guru模式的stap腳本來(lái)進(jìn)行編程:

// mapNULL.stp

%{

#include

#include

#include

pte_t * get_pte(struct task_struct *task, unsigned long address)

{

pgd_t* pgd;

pud_t* pud;

pmd_t* pmd;

pte_t* pte;

struct mm_struct *mm = task->mm;

static int nil = 0;

static pmd_t gpmd = {0};

static pte_t gpte = {0};

pgd = pgd_offset(mm, address);

if(pgd_none(*pgd) || pgd_bad(*pgd)) {

return NULL;

}

pud = pud_offset(pgd, address);

if(pud_none(*pud) || pud_bad(*pud)) {

return NULL;

}

pmd = pmd_offset(pud, address);

if(pmd_none(*pmd) || pmd_bad(*pmd)) {

*pmd = gpmd;

if(pmd_none(*pmd) || pmd_bad(*pmd)) {

return NULL;

}

}

pte = pte_offset_kernel(pmd, address);

if (nil != 0) {

pte->pte &= 0xfffffffffffff000;

*pte = gpte;

}

if(pte_none(*pte)) {

return NULL;

}

if (nil == 0) {

gpmd = *pmd;

gpte = *pte;

nil = 1;

}

return pte;

}

%}

function mapNULL:long(pid:long, addr:long)

%{

struct task_struct *task;

pte_t* pte;

void (*fun)(void);

fun = (void (*))0xffffffff81066090;

fun();

task = pid_task(find_pid_n***_ARG_pid, &init_pid_ns), PIDTYPE_PID);

if(!(pte = get_pte(task, STAP_ARG_addr))) {

STAP_RETVALUE = -1;

return;

}

fun();

if(get_pte(task, 0) == NULL) {

STAP_RETVALUE = -1;

return;

}

fun();

STAP_RETVALUE = 0;

%}

probe begin

{

mapNULL($1, $2);

exit();

}

下面演示一下效果,先看直接執(zhí)行access0,不加載內(nèi)核模塊的效果:

[root@localhost mod]# ./access0

pid=4172 addr=0x1c78010

段錯(cuò)誤

[root@localhost mod]#

很顯然,訪(fǎng)問(wèn)了“非法地址NULL”之后,收獲一個(gè)segfault。下面,我們結(jié)合內(nèi)核模塊再次來(lái)運(yùn)行access0:

[root@localhost mod]# ./access0

pid=4174 addr=0xf38010

另起一個(gè)終端,按照打印的pid和addr加載模塊:

[root@localhost mod]# stap -g mapNULL.stp 4174 0xf38010

[root@localhost mod]#

access0的終端敲入回車(chē):

[root@localhost mod]# ./access0

pid=4174 addr=0xf38010

0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x91 0x00 0x00 0x00 0x00 0x00 0x00 0x00

0x7a 0x68 0x65 0x6a 0x69 0x61 0x6e 0x67 0x20 0x77 0x65 0x6e 0x7a 0x68 0x6f 0x75

0x20 0x70 0x69 0x78 0x69 0x65 0x20 0x73 0x68 0x69 0x00 0x00 0x00 0x00 0x00 0x00

0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

[root@localhost mod]#

可以看到,第二行開(kāi)始的就是“zhejiang Wenzhou pixie shi ”了:

0x7a 0x68 0x65 0x6a 0x69 0x61 0x6e 0x67 0x20 0x77 0x65 0x6e 0x7a 0x68 0x6f 0x75

0x20 0x70 0x69 0x78 0x69 0x65 0x20 0x73 0x68 0x69 ...

那么第一行是什么呢?很顯然,used內(nèi)存是calloc返回的,這種內(nèi)存是被malloc內(nèi)存管理結(jié)構(gòu)鎖管理的,第一行的16字節(jié)就是這種管理機(jī)構(gòu),如果我們破壞掉它,那么在最后的free處就會(huì)出錯(cuò)。我們可以試一試:

// 打印NULL指針的前64個(gè)字節(jié)

for (i = 0; i < 4; i++) {

for (j = 0; j < 16; j++) {

printf("0x%0.2x ", *nilp);

if (i == 0) 將第一行16字節(jié)數(shù)據(jù)設(shè)置成0ff。

*nilp = 0xff;

nilp++;

}

printf(" ");

}

效果就是:

[root@localhost mod]# ./access0

pid=4184 addr=0x90a010

0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x91 0x00 0x00 0x00 0x00 0x00 0x00 0x00

0x7a 0x68 0x65 0x6a 0x69 0x61 0x6e 0x67 0x20 0x77 0x65 0x6e 0x7a 0x68 0x6f 0x75

0x20 0x70 0x69 0x78 0x69 0x65 0x20 0x73 0x68 0x69 0x00 0x00 0x00 0x00 0x00 0x00

0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

*** Error in `./access0': munmap_chunk(): invalid pointer: 0x000000000090a010 ***

======= Backtrace: =========

/lib64/libc.so.6(+0x7f5d4)[0x7f06b56705d4]

./access0[0x400789]

/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f06b56133d5]

./access0[0x4005c9]

======= Memory map: ========

00400000-00401000 r-xp 00000000 fd:00 38533721

通過(guò)重寫(xiě)NULL指針地址的映射頁(yè)表,我們成功訪(fǎng)問(wèn)了NULL指針,并且讀出了數(shù)據(jù)。

由于MMU的映射粒度是頁(yè)面,即4096字節(jié)(x86_64平臺(tái),也可以是別的值,比如2M),所以嚴(yán)格來(lái)講,“非法地址”并非只有NULL,而是從0到4096的一個(gè)頁(yè)面。

很多系統(tǒng)正是通過(guò)將NULL地址開(kāi)始的一個(gè)page映射到一個(gè)不可讀寫(xiě)不可訪(fǎng)問(wèn)的物理page來(lái)達(dá)到捕捉非法地址的效果的。

現(xiàn)在,我們把部分task_struct結(jié)構(gòu)體的內(nèi)存映射到NULL開(kāi)始的第一個(gè)虛擬地址空間頁(yè)面,通過(guò)修改task結(jié)構(gòu)體的comm來(lái)修改自己的名字,達(dá)到自省的目的。

修改自己名字的方法很多,prct就可以,但是本文通過(guò)映射task結(jié)構(gòu)體的方式進(jìn)行。

先看用戶(hù)態(tài)C代碼:

#include

#include

#include

int main(int argc, char **argv)

{

int i;

unsigned char *nilp = NULL;

// 為模塊提供信息。

printf("pid=%d addr=%p ", getpid(), used);

getchar();

// 在一個(gè)頁(yè)面范圍查找task的comm字段

for (i = 0; i < 4096; i++) {

// +2是為了跳過(guò)“./”,此處沒(méi)有進(jìn)行復(fù)雜的字符串解析

if (!memcmp(nilp, argv[0]+2, strlen(argv[0])-2)) {

printf("OK ");

// 更改comm字段為皮鞋濕

memcpy(nilp, "pixieshi", 8);

break;

}

nilp++;

}

printf(" ");

getchar();

free (used);

}

下面是對(duì)應(yīng)的內(nèi)核模塊:

// mapCOMM.c

// make -C /lib/modules/`uname -r`/build SUBDIRS=`pwd` modules

#include

#include

#include

#define DIRECT_MAP_START 0xffff880000000000

#define PAGE_TABLE_E 0x8000000000000000

static int pid = 16790;

module_param(pid, int, 0644);

static unsigned long addr = 0;

module_param(addr, long, 0644);

static int nil = 0;

static pmd_t gpmd = {0};

static pte_t gpte = {0};

static unsigned long tskp;

void (*fun)(void);

static pte_t* get_pte(struct task_struct *task, unsigned long address)

{

pgd_t* pgd;

pud_t* pud;

pmd_t* pmd;

pte_t* pte;

struct mm_struct *mm = task->mm;

pgd = pgd_offset(mm, address);

if(pgd_none(*pgd) || pgd_bad(*pgd)) {

return NULL;

}

pud = pud_offset(pgd, address);

if(pud_none(*pud) || pud_bad(*pud)) {

return NULL;

}

pmd = pmd_offset(pud, address);

if(pmd_none(*pmd) || pmd_bad(*pmd)) {

*pmd = gpmd;

if(pmd_none(*pmd) || pmd_bad(*pmd)) {

return NULL;

}

}

pte = pte_offset_kernel(pmd, address);

if (nil != 0) {

pte->pte = tskp;

}

if(pte_none(*pte)) {

return NULL;

}

if (nil == 0) {

pte_t p = *pte;

gpmd = *pmd;

gpte = p;

nil = 1;

}

return pte;

}

static int mapCOMM_init(void)

{

struct task_struct *task;

pte_t* pte;

int tsk_off;

struct page* page;

fun = 0xffffffff81066090;

fun();

task = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);

tskp = (unsigned long)task;

tskp -= DIRECT_MAP_START;

tsk_off = tskp & 0xfff;

#define COMM_OFF 1872

// 保證可以在一個(gè)頁(yè)面內(nèi)找到comm字段

if (tsk_off + COMM_OFF > 0xfff) {

tskp += 0x1000;

}

// 頁(yè)面對(duì)齊

tskp &= 0xfffffffffffff000;

tskp += PAGE_TABLE_E;

// 用戶(hù)態(tài)讀寫(xiě)權(quán)限

tskp |= 0x67;

if(!(pte = get_pte(task, addr)))

return -1;

fun();

if(!(pte = get_pte(task, 0)))

return -1;

fun();

return -1;

}

static void mapCOMM_exit(void)

{

}

module_init(mapCOMM_init);

module_exit(mapCOMM_exit);

MODULE_LICENSE("GPL");

編譯后備用。我們先運(yùn)行我們的skinshoe進(jìn)程。

[root@localhost mod]# ./skinshoe

pid=4216 addr=0x22d4010

獲得輸出信息后,另起終端,加載模塊,輸入skinshoe打印的信息:

[root@localhost mod]# insmod ./mapCOMM.ko pid=4216 addr=0x22d4010

insmod: ERROR: could not insert module ./mapCOMM.ko: Operation not permitted

此時(shí)skinshoe進(jìn)程的運(yùn)行終端看看進(jìn)程的名字有沒(méi)有改變:

[root@localhost mod]# cat /proc/4216/comm

pixieshi

[root@localhost mod]# ps -e|grep 4216

4216 pts/4 00:00:00 pixieshi

OK,已經(jīng)改成“皮鞋濕”了。

當(dāng)然了,合法訪(fǎng)問(wèn)NULL指針其實(shí)有更加“正規(guī)”的做法,即修改內(nèi)核參數(shù):

[root@localhost stap]# sysctl -a|grep vm.mmap_min_addr

vm.mmap_min_addr = 4096

[root@localhost stap]# sysctl -w vm.mmap_min_addr=0

vm.mmap_min_addr = 0

[root@localhost stap]# sysctl -a|grep vm.mmap_min_addr

vm.mmap_min_addr = 0

[root@localhost stap]#

然后使用mmap系統(tǒng)調(diào)用將指針FIXed map到地址0即可。

說(shuō)一下本文的緣起以及一些例行的形而上的意義。

前天晚上,有位朋友問(wèn)了我一個(gè)問(wèn)題,為了備忘,我昨天發(fā)了一則朋友圈:

昨天有人問(wèn)我說(shuō)為什么NULL指針不能訪(fǎng)問(wèn),我說(shuō)NULL指針是可以訪(fǎng)問(wèn)的,NULL就是0,0也是一個(gè)合法地址,為什么不能訪(fǎng)問(wèn)?之所以一訪(fǎng)問(wèn)NULL就會(huì)收獲一個(gè)段錯(cuò)誤純粹是編程意義上的人為規(guī)定,不存在操作系統(tǒng)硬件層面的硬性機(jī)制阻止NULL指針被訪(fǎng)問(wèn)。為此,我還專(zhuān)門(mén)寫(xiě)了一個(gè)demo,修改頁(yè)表項(xiàng)為NULL地址映射一個(gè)物理頁(yè)面,NULL地址不光可以讀寫(xiě),還能修改進(jìn)程名字呢。char *p;char *p = NULL;以上二者是不同的,上面那個(gè)p指針是“無(wú)”,而下面那個(gè)p則是“空”,“無(wú)”是什么都沒(méi)有,“空”是實(shí)實(shí)在在的空,仔細(xì)體會(huì)這種略帶哲學(xué)意味的區(qū)別。

關(guān)于“空”和“無(wú)”,在C/C++編程規(guī)范上特別要注意:

防止訪(fǎng)問(wèn)空指針:訪(fǎng)問(wèn)指針前要判斷NULL。

杜絕野指針:釋放指針后要設(shè)置NULL。

總之,我們要依靠“空”,避開(kāi)“無(wú)”。

“無(wú)”是什么都沒(méi)有,薛定諤的無(wú),“空”是實(shí)實(shí)在在的空,空為萬(wàn)物,萬(wàn)物皆空。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    7152

    瀏覽量

    125624
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7632

    瀏覽量

    141819
  • null
    +關(guān)注

    關(guān)注

    0

    文章

    19

    瀏覽量

    4129

原文標(biāo)題:Linux C程序真的不能訪(fǎng)問(wèn)NULL指針嗎?

文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    RT-Thread SPI鏈?zhǔn)絺鬏敺欠?b class='flag-5'>訪(fǎng)問(wèn)?揭秘致命陷阱!

    structrt_spi_message的next指針。由于next未賦值為RT_NULL,鏈?zhǔn)絺鬏敃r(shí)觸發(fā)非法內(nèi)存訪(fǎng)問(wèn)(next指向不可控地址)。修復(fù)方案:將next顯式置空后,
    的頭像 發(fā)表于 06-24 19:38 ?1083次閱讀
    RT-Thread SPI鏈?zhǔn)絺鬏敺欠?b class='flag-5'>訪(fǎng)問(wèn)</b>?揭秘致命陷阱!

    函數(shù)指針的六個(gè)常見(jiàn)應(yīng)用場(chǎng)景

    函數(shù)指針在嵌入式開(kāi)發(fā)中有著廣泛的應(yīng)用,它讓代碼更加靈活,減少冗余,提高可擴(kuò)展性。很多時(shí)候,我們需要根據(jù)不同的情況動(dòng)態(tài)調(diào)用不同的函數(shù),而函數(shù)指針正是實(shí)現(xiàn)這一需求的重要工具。本文將介紹六個(gè)常見(jiàn)的函數(shù)指針
    的頭像 發(fā)表于 04-07 11:58 ?546次閱讀
    函數(shù)<b class='flag-5'>指針</b>的六個(gè)常見(jiàn)應(yīng)用場(chǎng)景

    指針式萬(wàn)用表功能介紹

    基于電磁感應(yīng)原理。當(dāng)電流通過(guò)表頭的線(xiàn)圈時(shí),會(huì)產(chǎn)生磁場(chǎng),這個(gè)磁場(chǎng)與永久磁鐵的磁場(chǎng)相互作用,使指針偏轉(zhuǎn)。指針的偏轉(zhuǎn)角度與通過(guò)線(xiàn)圈的電流成正比,從而實(shí)現(xiàn)對(duì)電流的測(cè)量。對(duì)于電壓和電阻的測(cè)量,則是通過(guò)對(duì)電路進(jìn)行適當(dāng)?shù)呐渲?,利?/div>
    的頭像 發(fā)表于 01-23 09:12 ?1903次閱讀

    指針式萬(wàn)用表使用指南

    一、指針式萬(wàn)用表簡(jiǎn)介 指針式萬(wàn)用表是一種傳統(tǒng)的電子測(cè)量工具,因其表頭指針的擺動(dòng)來(lái)顯示測(cè)量結(jié)果而得名。與數(shù)字萬(wàn)用表相比,指針式萬(wàn)用表在某些情況下能提供更直觀(guān)的讀數(shù),尤其是在測(cè)量快速變化的
    的頭像 發(fā)表于 01-22 17:25 ?1756次閱讀

    指針式萬(wàn)用表測(cè)量精度比較

    指針式萬(wàn)用表的核心是一個(gè)可變電阻器(分壓器)和一個(gè)可動(dòng)的指針。當(dāng)測(cè)量電壓或電流時(shí),通過(guò)分壓器的電阻值會(huì)改變,從而改變通過(guò)指針的電流,使指針
    的頭像 發(fā)表于 01-22 17:23 ?857次閱讀

    指針被釋放后就變成了空指針

    指針被釋放后,是不是就變成了空指針?有好多同學(xué)提出了這樣的問(wèn)題。 借用《C專(zhuān)家編程》上面的一段代碼,可以很好的解釋這個(gè)問(wèn)題。 ? ? #include int main(){ char *s
    的頭像 發(fā)表于 01-22 09:23 ?396次閱讀

    善用Optional,告別NPE

    作者:京東物流 王亞寧 1、NPE是什么? NPE:NullPointerException(空指針異常)。可以說(shuō)自Null的誕生以來(lái)它就讓無(wú)數(shù)的程序員為之哀嚎,也是無(wú)數(shù)系統(tǒng)Bug的來(lái)源。托尼·霍爾
    的頭像 發(fā)表于 12-18 09:46 ?1060次閱讀

    C語(yǔ)言程序設(shè)計(jì)教程第4版第8講:指針

    C語(yǔ)言指針講解
    發(fā)表于 11-20 14:10 ?6次下載

    C語(yǔ)言指針學(xué)習(xí)筆記

    本文從底層內(nèi)存分析,徹底讓讀者明白C語(yǔ)言指針的本質(zhì)。
    的頭像 發(fā)表于 11-05 17:40 ?650次閱讀
    C語(yǔ)言<b class='flag-5'>指針</b>學(xué)習(xí)筆記

    C語(yǔ)言指針運(yùn)算符詳解

    在C語(yǔ)言中,當(dāng)你有一個(gè)指向數(shù)組中某個(gè)元素的指針時(shí),你可以對(duì)該指針執(zhí)行某些算術(shù)運(yùn)算,例如加法或減法。這些運(yùn)算可以用來(lái)遍歷數(shù)組中的元素,如ptr[i]等價(jià)于*(ptr + i)。然而,如果你的操作使得指針指向了數(shù)組以外的位置(除了數(shù)
    的頭像 發(fā)表于 10-30 11:16 ?797次閱讀

    海外爬蟲(chóng)IP的合法邊界:合規(guī)性探討與實(shí)踐

    海外爬蟲(chóng)IP的合法邊界主要涉及合規(guī)性探討與實(shí)踐。
    的頭像 發(fā)表于 10-12 07:56 ?613次閱讀

    電流計(jì)指針偏轉(zhuǎn)方向是正極還是負(fù)極

    電流計(jì)指針的偏轉(zhuǎn)方向并非簡(jiǎn)單地指向正極或負(fù)極,而是取決于電流的流入方向以及電流計(jì)正負(fù)極的連接方式。以下是對(duì)這一問(wèn)題的分析: 一、電流流入方向與指針偏轉(zhuǎn)的關(guān)系 常規(guī)情況 : 對(duì)于常規(guī)的電流計(jì)(假設(shè)其
    的頭像 發(fā)表于 09-19 15:18 ?9853次閱讀

    C語(yǔ)言指針詳細(xì)解析

    指針,野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒(méi)有明確限制的),其值是隨機(jī)的,指針變量的值是別的變量的地址,意味著
    發(fā)表于 09-14 10:03

    IP 地址欺騙:原理、類(lèi)型與防范措施

    ,使其數(shù)據(jù)包看起來(lái)像是來(lái)自合法的源地址從而欺騙目標(biāo)系統(tǒng)或網(wǎng)絡(luò),最終非法訪(fǎng)問(wèn)、竊取信息或破壞網(wǎng)絡(luò)正常運(yùn)行的目的。 IP地址欺騙的工作原理是什
    的頭像 發(fā)表于 08-26 14:04 ?903次閱讀
    IP <b class='flag-5'>地址</b>欺騙:原理、類(lèi)型與防范措施

    面試???1:函數(shù)指針指針函數(shù)、數(shù)組指針指針數(shù)組

    在嵌入式開(kāi)發(fā)領(lǐng)域,函數(shù)指針、指針函數(shù)、數(shù)組指針指針數(shù)組是一些非常重要但又容易混淆的概念。理解它們的特性和應(yīng)用場(chǎng)景,對(duì)于提升嵌入式程序的效率和質(zhì)量至關(guān)重要。一、
    的頭像 發(fā)表于 08-10 08:11 ?1464次閱讀
    面試???1:函數(shù)<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>函數(shù)、數(shù)組<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>數(shù)組