Software Engineering Lecture s3
Menu Menu
型 (type)
コンピュータでは、すべてのデータはbinary pattern (1,0の有限な列)で表される。そのパターンに意味を見出すのは人間であり、人間がプログラムした命令列である。コンピュータの命令列は、特定のbinary pattern に結びつけられている。特に、
数値としてのパターン (符号無し整数、2の補数、浮動小数点) メモリの配列の場所を表すアドレス CPUの命令を表すパターンはコンピュータの中で特別扱いされる。これらを間違えないように識別するために型(type)という工夫が有効である。
Pointer
メモリのアドレスはCPUによって16bit,32bit,64bit で表される。OSの授業で勉強したように、これらのアドレスは直接にメモリアドレスに対応するとは限らない。アドレスにも区別があり、これらは通常は領域で管理される。しかし、アドレスの先を示す型を使用して区別しても良い。型にID (identifier 特別な番号、タグとも呼ばれる)をつけて、それを明示的にアドレスと併用するという手もある。その方が実行時に型のチェックができてうれしいが、余計なメモリを消費する。
問題3.1
Poiner 関係の良くある間違い以下のコードの間違いを指摘し、実際に不都合が起きることを確認せよ。
int f(int arg) { int *p; *p = arg; return *p; }以下のコードのBuffer Overflow を指摘し、これが daemon 経由で実行された時に、任意のコードを実行するにはどうしたら良いかを示せ。(単にクラッシュさせるだけではだめ)
#include <stdio.h> int weakCode() { char buf[32]; scanf("%s\n",buf); printf("Input: %s\n",buf); return 1; }以下のコードで起きる不都合を実証せよ。
#include <malloc.h> char * getMem() { return (char*)malloc(32); } void fillMem(char *p) { int i; for(i=0;i<50;i++) { p[i] = ' '; } } void test { char p[10]; for(i=0;i<10;i++) { p[i] = getMem(); } for(i=0;i<10;i++) { fillMem(p[i]); } for(i=0;i<10;i++) { free(p[i]); } }
Fail-Safe C
https://staff.aist.go.jp/y.oiwa/FailSafeC/
C の型宣言
ポインタを含む C の型宣言の構文は複雑である。
* と [] の結合の優先順位 関数を表す後置された()と、通常の()の扱い -> の扱い cast (型変換)の構文と通常の定義の違いに注意しよう。
char *p[]; は、 (char *)(p[]) char *f(); は、 (char *)f()
Cのデータ型とポインタ、そして、ポインタの指す先
C のデータ型を定義するときには、必ず typedef を使うようにしよう。
ポインタの指し示す先を保証すること。
malloc() の使い方 free()の使い方free()したポインタを手元に残さない。
** を使わずに、typedef を使用する。
キューの例題 を見て使い方を勉強しよう。
問題3.2
C言語で以下の型の変数宣言は何を表すのか。日本語または英語で説明せよ。また、その型をtypedefで宣言する例題を作れ。さらに、void *p から以下の型の変数q に代入する場合の cast の構文を示せ。コンパイラを用いて
- char *q
- int *(*q)(float,char *)
- int (*q[])()
以下の型の変数をCで宣言せよ
- 文字の配列へのポインタ
- 文字へのポインタの配列
- 文字へのポインタの配列を返す関数
実際に、C compiler で正しく解釈されていることをチェックせよ。
型の整合性の検査
型の整合性の検査には、Unification (単一化)という方法が知られている。この方法では特に、一部に不定の型があった時に、その型に関する特殊化の度合いも知ることができる。不定の型は「タイプ変数」とも呼ばれる。C++ ではテンプレートと呼ばれる機能により限られた意味でのタイプ変数を使うことができる。MLと呼ばれる言語では、タイプ変数と型の単一化が積極的に使われており効果を挙げている。MLは計算理論のグループの間では良く使われている。