Try   HackMD

2019q1 第 4 週測驗題 (上)

目的: 檢驗學員對 C 程式設計的認知


測驗 1

考慮到以下簡易的 reference counting 實作:

#include <stdlib.h>

#define REF_TYPE(type) ref_to_##type *
#define REF_DEFINE(type)                                                     \
    typedef struct P {                                       \
        unsigned c, l;                                                       \
        type *o;                                                             \
    } ref_to_##type;                                                         \
    REF_TYPE(type) ref_new_##type()                                          \
    {                                                                        \
        type *o = (type *) malloc(sizeof(type));                             \
        REF_TYPE(type) r = ((REF_TYPE(type)) malloc(sizeof(ref_to_##type))); \
        r->o = o;                                                            \
        r->c = 0;                                                            \
        r->l = 0;                                                            \
        return r;                                                            \
    }
#define ref_new(type) ref_new_##type()
#define ref_acquire(ref) \
    {                    \
        ref->c++;        \
        ref->l++;        \
    }
#define ref_release(ref) \
    if (Q) {     \
        free(ref->o);    \
        free(ref);       \
    }
#define ref_val(ref) R

#include <stdio.h>
#include <string.h>

typedef struct {
    char hello[32]; long number; } foo;

REF_DEFINE(foo);

void bar(REF_TYPE(foo) x) {
    ref_acquire(x);
    printf("%s\n", ref_val(x).hello);
    ref_val(x).number = 123;
    ref_release(x);
}

int main(int argc, char **argv) {
    REF_TYPE(foo) x;

    x = ref_new(foo);
    ref_acquire(x);

    strncpy(ref_val(x).hello, "Hello world!", 32);

    bar(x);
    printf("%ld\n", ref_val(x).number);

    printf("\n");
    printf("total acquisitions: %d\n", S);
    printf("current references: %d\n", T);

    ref_release(x);
    return 0;
}

預期執行輸出如下:

Hello world!
123

total acquisitions: 2
current references: 1

請補完程式碼

作答區

P = ?

  • (a) ref_to_#type#
  • (b) ref_to_##type##_s
  • (c) ref_to_#type

Q = ?

  • (a) --ref->c
  • (b) --(ref->c)
  • (c) (ref->c)--
  • (d) !--ref->c
  • (e) &--ref->c

R = ?

  • (a) ref
  • (b) *ref
  • (c) &ref
  • (d) *ref->o
  • (e) (*(ref->o))

S = ?

  • (a) x
  • (b) x->o
  • (c) x->c
  • (d) x->l

T = ?

  • (a) x
  • (b) x->o
  • (c) x->c
  • (d) x->l

延伸問題:

  1. 在 Linux 核心找出類似的 reference counting 程式碼並解說;
  2. 用上述的 reference counting 解釋 lsmod 命令輸出的 Used by 運作原理,需要分析程式碼並設計實驗