2024q1 Homework2 (quiz1+2)

contributed by < timmy61109 >

開發環境

$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ lscpu
Architecture:            x86_64
  CPU op-mode(s):        32-bit, 64-bit
  Address sizes:         43 bits physical, 48 bits virtual
  Byte Order:            Little Endian
CPU(s):                  12
  On-line CPU(s) list:   0-11
Vendor ID:               AuthenticAMD
  Model name:            AMD Ryzen 5 2600 Six-Core Processor
    CPU family:          23
    Model:               8
    Thread(s) per core:  2
    Core(s) per socket:  6
    Socket(s):           1
    Stepping:            2
    Frequency boost:     enabled
    CPU max MHz:         3400.0000
    CPU min MHz:         1550.0000
    BogoMIPS:            6800.03
    Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mc
                         a cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall n
                         x mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_go
                         od nopl nonstop_tsc cpuid extd_apicid aperfmperf rapl p
                         ni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe
                          popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy sv
                         m extapic cr8_legacy abm sse4a misalignsse 3dnowprefetc
                         h osvw skinit wdt tce topoext perfctr_core perfctr_nb b
                         pext perfctr_llc mwaitx cpb hw_pstate ssbd ibpb vmmcall
                          fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushop
                         t sha_ni xsaveopt xsavec xgetbv1 clzero irperf xsaveerp
                         tr arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clea
                         n flushbyasid decodeassists pausefilter pfthreshold avi
                         c v_vmsave_vmload vgif overflow_recov succor smca sev s
                         ev_es
Virtualization features: 
  Virtualization:        AMD-V
Caches (sum of all):     
  L1d:                   192 KiB (6 instances)
  L1i:                   384 KiB (6 instances)
  L2:                    3 MiB (6 instances)
  L3:                    16 MiB (2 instances)
NUMA:                    
  NUMA node(s):          1
  NUMA node0 CPU(s):     0-11
Vulnerabilities:         
  Gather data sampling:  Not affected
  Itlb multihit:         Not affected
  L1tf:                  Not affected
  Mds:                   Not affected
  Meltdown:              Not affected
  Mmio stale data:       Not affected
  Retbleed:              Mitigation; untrained return thunk; SMT vulnerable
  Spec rstack overflow:  Mitigation; safe RET
  Spec store bypass:     Mitigation; Speculative Store Bypass disabled via prctl
  Spectre v1:            Mitigation; usercopy/swapgs barriers and __user pointer
                          sanitization
  Spectre v2:            Mitigation; Retpolines, IBPB conditional, STIBP disable
                         d, RSB filling, PBRSB-eIBRS Not affected
  Srbds:                 Not affected
  Tsx async abort:       Not affected

開發過程

題目 1

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.

有點難找,但我找到了嗯嗯

參考資料:

題目 2

閱讀〈基於 C 語言標準研究與系統程式安全議題〉,考慮 int *ptr = malloc(sizeof(int)); *ptr = 15; free(ptr); printf("%d", *ptr); 這段程式碼會導致 dangling pointer,請指出會因 dangling pointer 受影響的敘述,寫出該敘述 (不是行號)

https://zh.wikipedia.org/zh-tw/未定义行为

https://en.cppreference.com/w/c/language/behavior

我的答案:雖然有透過指標方式將 15 資料指向 ptr ,但因為儲存空間 ptrfree 了,但仍然要存取 *ptr 的資料,會被發現該指標未有資料而無法得到資料。

請教 ChatGPT : 根據《基於 C 語言標準研究與系統程式安全議題》的內容,當一塊記憶體被釋放後,如果仍然有指針指向這塊記憶體區域,則會產生 dangling pointer 問題。dangling pointer 會對受影響的程式碼造成不可預測的行為,因為釋放後的記憶體可能已經被重新分配給其他用途,導致原指標指向的內容被修改,或者指標指向的內容變得不可靠。

在這段程式碼中,當指標 ptr 通過 free(ptr) 進行釋放後,指標 ptr 變成了懸空指標 (dangling pointer)。之後的 printf("%d", *ptr); 試圖解引用這個已經被釋放的記憶體位置,這將導致未定義行為。這是因為該記憶體可能已經被系統重新分配給其他用途,或者被標記為未定義的狀態,因此無法確保在解引用時會得到預期的結果。

題目 3

考慮 struct S { unsigned b1 : 5; unsigned :0; unsigned b2 : 6; unsigned b3 : 15; }; 試問 sizeof(struct S) 通常的結果為何?請以 C 語言規格解釋

我的回答:

通常結果為 15 格,因為依照 C99 描述,使用 5 、 6 、 15 之間的大小,會以最大的作為依據,因此依照 C99 描述,應該要為 15 大小,但實際仍需要看編譯器為主。

A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.

ChatGPT 回答:

根據 C99 標準規範,在一個結構中,位字段的處理方式在第6.7.2.1節中有所描述。在結構中,位字段之間可以存在「無名」位字段,其目的是為了實現成員的對齊要求。在提供的 struct S 結構中,unsigned :0; 就是一個無名的位字段,其寬度為0。這個字段的存在對結構的對齊起到了作用,但它不會佔用任何實際的位元。

在 C99 標準中,6.7.2.1節描述了位字段的分配規則:

「位字段必須具有 _Bool、signed int、unsigned int 或其他實現定義類型的合格或非合格版本。是否允許原子型別是由實現定義的。」

「沒有聲明符號,只有一個冒號和寬度的位字段聲明,表示一個無名的位字段。作為一個特殊情況,具有0寬度的位字段結構成員表示不要將更多的位字段填充到前一個位字段所在的單元中。」

這段規範強調了位字段必須具有指定的類型,並描述了無名位字段的情況,即它們用於實現對齊要求,但本身不佔用實際位元數。

根據 C99 標準的這些規則,struct S 的大小通常將是其所需對齊的大小,而無名位字段不會增加結構的大小,因此 sizeof(struct S) 的結果通常將是對齊要求的大小。

題目 4

參照〈你所不知道的 C 語言: bitwise 操作〉,已知 uint16_t rev16(uint16_t n) { n = ((n & 0xff00) >> 8) | ((n & 0x00ff) << 8); n = ((n & 0xf0f0) >> 4) | ((n & 0x0f0f) << 4); n = ((n & 0xcccc) >> 2) | ((n & 0x3333) << 2); n = ((n & 0xaaaa) >> 1) | ((n & XXXX) << 1); return n; } 可將給定的 16 位元無號整數逐位元反轉順序,試問 XXXX 是什麼?以 Hexadecimal integer literals 回覆

依照補數的定義作為計算,最後的結果就是要等於互補。

依照 0xff000x00ff0xf0f00x0f0f0xcccc0x3333 之間互補,透過移位方式做到測試。因此 0xaaaaa 轉換為 bit ,應該會等於 1010 ,如果補數則 0101 則為 5 ,因此為 0x5555

Select a repo