google-code-prettify

ラベル C の投稿を表示しています。 すべての投稿を表示
ラベル C の投稿を表示しています。 すべての投稿を表示

2009-12-10

x86のmisalignアクセス時に例外を起こす方法

x86ではmisalignアクセス時でも、例外を起こさずにアクセスする事ができる。
例えば次のコード

long *p;
char buf[32];
p = (long*)&buf[1];

*p = 0;

は、misalignアクセスであり、多くのプロセッサでは例外が発生する。

x86でも同様に例外を発生させてやるには、EFLAGSレジスタのbit18、AC(Alignment Check)ビットを1にしてやれば良い。

gccのインラインアセンブラの例。

__asm__ __volatile__ (
"pushf\n"
"\tpopl %%eax\n"
"\tor $0x00040000, %%eax\n"
"\tpushl %%eax\n"
"\tpopf\n"
:::"%eax");


これが何の役に立つかと言うと、
・misalignアクセスで例外が発生するプロセッサ上で動作させるコードを作成したい。
・でも、そのテストはx86(Linuxなど)上で行いたい。
という場合。

参考:
X86 Assembly/X86 Architecture
Mis-aligned pointers on x86
GCC Inline Assembler


09/12/11 追記:
この機能、実はあまり使えないような気がしてきた。
なぜなら、glibcはACが0である事を期待したコードになっていて、ACを1にするとglibcの関数で落ちるから。

2009-12-06

pmccabe - プログラムの複雑度を測定する

pmccabe
CやC++のプログラムの循環的複雑度を計測してくれるツール。

改行コードがCRLFのファイルにpmccabeをかけると、以下のようなエラーがでる。

"a.c", line 187: too many }'s

これを防ぐには、pmccabeに通す前にソースコードの改行コードをLFに書き換えるか、pmccabe自体を以下の様に変更すれば良い。

--- pmccabe.h.orig 2009-12-06 23:36:37.000000000 +0900
+++ pmccabe.h 2009-12-06 23:26:15.000000000 +0900
@@ -133,7 +133,7 @@
stats_t *stats_pop(stats_t *sp);
void stats_accumulate(stats_t *sp);

-#define ISSPACE(c) ((c) == T_NCNULINE || (c) == '\n' \
+#define ISSPACE(c) ((c) == T_NCNULINE || (c) == '\n' || (c) == '\r'\
|| (c) == '\t' || (c) == ' ')

#define ISIDENT1(c) (((c) >= 'a' && (c) <= 'z') \

2009-12-04

Cで、constなポインタからconstをはずす方法

constなポインタからconstをはずすキャストをすると、コンパイラのwarningが出る事がある。

const void *p;
void *p2;

p = xxx;
p2 = (void*)p; ←ココ。

明示的にキャストしているから問題ないような気もするのだが、warningは出てしまう。

一度longにキャストするという手もある。

p2 = (void*)(long)p;

しかしこれだと、「ポインタのサイズとlongのサイズは同じなのか?」問題があり、スッキリしない。

以下のようにunionを使うと、コンパイラをだまらせる事ができ、しかもスッキリと問題が解決する。

union {
void *vp;
const void *cvp;
} u;

u.cvp = p;
p2 = u.vp;

2008-09-04

signedの比較 - 答え

前回の答え。

long a = 0x80000000;
long b = 1;

if (a - b > 0) {
printf("hello");
} else {
printf("world");
}

これは、helloではなくworldが出力される事もある。

なぜかと言うと…

Cでは、signedの計算でオーバーフローした時の動作は、未定義。
そのためコンパイラは、「signedの計算はオーバーフローしない」と思って最適化をかける事がある。

コンパイラの最適化の結果、a-b>0が、a>bに変換されると、以下のコードになる。

long a = 0x80000000;
long b = 1;

if (a > b) {
printf("hello");
} else {
printf("world");
}

この場合、aは負、bは正なので、worldが出力される事になる。

2008-09-03

signedの比較

社内で出したクイズ。

以下のコードは、何が出力されるでしょう。longは32bitとした場合。

long a = 0x80000000;
long b = 1;

if (a - b > 0) {
printf("hello");
} else {
printf("world");
}

答えは次回。

2008-07-22

ソースコードのコメントに書くべき事

ソースコードは、何をしているかは(ある程度)表す事ができるが、以下の点は表現する事ができない。
・なぜそうしているか。
・他の選択肢には何があったか。なぜそれらではダメなのか。
・どういった思想で作っているのか。

これらの点はコメントとして記述するべき。

2008-05-19

Cでのポインタの読み方

社内ゼミ用資料。ゼミの内容がマニアックな内容になってきたので、今回は軽い話題にした。

int (*p[5])[3];
char (*(*fp)(void))(int);

などの読み方。

http://sakurai.sumomo.ne.jp/page/c_pointer

2007-08-18

C言語を覚えるためのボードゲーム

c-jump
C言語を覚えるためのボードゲーム。

あまり楽しめるゲームには見えないが、ネタとして買うのはおもしろそう。

via hubertf's NetBSD blog

2007-05-24

OpenMP - マルチプロセッサプログラミングの手法

OpenMPでは並列処理の指示を#pragmaで行うので、
  • 既存のコードにちょっとpragmaを追加するだけで、並列処理ができるようになる。
  • OpenMP非対応のコンパイラでも、そのままコンパイルできる。
といったMPI(Message Passing Interface)には無いメリットがある。
gccでは、4.2からOpenMPがサポートされている。

公式ページ
wikipediaでのOpenMPの説明

2006-12-18

mallocを使う時はmalloc.hではなくstdlib.hをインクルードしなくてはならない

知らなかった…。今までmalloc.hをインクルードしていたよ…。

FreeBSDの/usr/include/malloc.hは、以下のようになっている。
/* $FreeBSD: src/include/malloc.h,v 1.5 2001/11/07 23:14:31 obrien
Exp $ */
#if __STDC__
#error "<malloc.h> has been replaced by <stdlib.h>"
#else
#include <stdlib.h>
#endif


via tech-pkg@netbsd

2006-11-16

gccの定義済みマクロを調べる方法

gccの定義済みマクロを見るには、

$ touch a.h; cpp -dM a.h

とすれば良い。
一覧とその説明はこちら

2006-11-08

カナリヤ

stackへの攻撃を検知するために、スタック上のスタック情報とローカル変数の間にガードデータを入れるという方法があるが、このガードデータの事をcanary(カナリヤ)と言うらしい。

毒ガスの検知のみならず、stack攻撃の検知にも使われるかわいそうなカナリヤ…。