【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.20858

マルチスレッドの時のmemset
投稿者---まりー(2005/04/28 15:10:35)


LedHat Linux ES release 4 でgccで64bitで開発してます。
シングルスレッドの時はいいのですが、マルチスレッドの時に、
ABC1構造体のゼロクリアがされない箇所があります。
アライメントを揃えるために、bの前と、dの後にパディングがされるようです。
最適化(-O3)などによって未使用の領域とみなされゼロクリアが
されないのではないかと思ったのですが、
マルチスレッドの時のみなぜそのような現象が起こるかわかりません。
現在はABC2のように構造体のメンバを隙間なく並べる事で回避していますが、
原因が解る方がいらっしゃいましたらよろしくお願いします。

#include <string.h>

/*アライメントを揃えるためにパディングされる*/
/*構造体サイズ 40*/
typedef struct  _abc1{
    unsigned int a;
    
    unsigned long long b;

    unsigned int c;

    unsigned char d[16];
}ABC1;

/*メンバが隙間なく並べられる */
/*構造体サイズ 32*/
typedef struct  _abc2{
    unsigned long long b;

    unsigned int a;

    unsigned int c;

    unsigned char d[16];
}ABC2;

void zero_clear ()
{
    ABC1 x1;
    ABC2 x2;
    
    memset(&x1,0,sizeof(ABC1));  /*マルチスレッドの時、ゼロクリアされない箇所がある。*/
    memset(&x2,0,sizeof(ABC2)); /*すべてゼロクリアされる。*/

    return;
}




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:マルチスレッドの時のmemset 20860 あかま 2005/04/28 18:43:20


No.20860

Re:マルチスレッドの時のmemset
投稿者---あかま(2005/04/28 18:43:20)


このコードからは判断できないと思います。
ゼロクリアしてる関数と、呼び出し元の関数ぐらいはそのまま載せたほうがよいかと。

考えられる要因としては、
x2.d[16]あたりに書き込んでるせいで、x1に影響が。
とか
一時変数をゼロクリアして、そのアドレスを返して使っている
とか



この投稿にコメントする

削除パスワード

No.20862

Re:マルチスレッドの時のmemset
投稿者---まりー(2005/04/28 21:37:58)


>このコードからは判断できないと思います。
>ゼロクリアしてる関数と、呼び出し元の関数ぐらいはそのまま載せたほうがよいかと。

あまり変わらないかと思われるのですが、
呼び出し方としては、下のコード通りです。

領域外へのアクセスなどはしていないと思います。
また、最初の発言の通り、現在は構造体の中のメンバの順序を変えると、
memsetによるゼロクリアは成功します。
また、memsetを使わずに、
構造体領域全体(パディング部分も含む)に対して1バイトずつ0を代入していく
処理をする事でも回避できるようです。

また、パディングされているだろう部分がmemset通過後も
ゼロクリアされてないのも確認しています。
でも、それがなぜ、マルチスレッドの時にだけ起きるのか解らないのです。



typedef struct  _abc{
    unsigned int a;
    
    unsigned long long b;

    unsigned int c;

    unsigned char d[16];
}ABC;



void abc_init(ABC *abc)
{
    memset(abc,0,sizeof(ABC));
    return;
}


int main()
{
    ABC *abc;

    abc = (ABC *)malloc(sizeof(ABC));

    abc_init(abc);

    free(abc);

    return 0;
}






この投稿にコメントする

削除パスワード

No.20863

Re:マルチスレッドの時のmemset
投稿者---とおりすがり(2005/04/29 05:37:58)


>LedHat Linux ES release 4 でgccで64bitで開発してます。

Redhatね。64ビット環境が手元にある人はそう多くなさそうだから、
0クリアされないことを確認した結果を載せるべきかと思います。
当然、sizeofの値も。
# どう確認したのか、どのように0クリアされていないのか。

普通に考えれば、memsetは構造体のパディングなんかとは無関係なレイヤ
なので、一部のみセットされるなんてことはなさそうですが…


この投稿にコメントする

削除パスワード

No.20866

Re:マルチスレッドの時のmemset
投稿者---まりー(2005/04/29 09:21:00)


>Redhatね。
失礼しました。(恥)

>0クリアされないことを確認した結果を載せるべきかと思います。
>当然、sizeofの値も。
># どう確認したのか、どのように0クリアされていないのか。
下のコードのように確認しました。

int main()
{
    ABC *abc;
    int i;
    size_t size=0;

    abc = (ABC *)malloc(sizeof(ABC));

    abc_init(abc); /*ABC構造体をゼロクリア*/

    size = sizeof(ABC);

    printf("ABC size: %d\n",size);
    for(i=0;i<size;i++)
    {
    printf("%02X",((unsigned char *)abc)[i]);
    }

    free(abc);

    return 0;
}


出力結果
ABC size: 40
0000000000000000000000000000000000000000000000000000000000000000000000004A000000
[  a   ][ pad? ][      b       ][   c  ][              d               ][ pad? ]

または、

ABC size: 40
00000000580000000000000000000000000000000000000000000000000000000000000000000000
[  a   ][ pad? ][      b       ][   c  ][              d               ][ pad? ]


[ ]は私が後づけしたものです。
何度か繰り返すと、パディング部分だと思われる所のどちらかに
0クリアされてない箇所があります。

また、メンバをそれぞれ個別で表示させるとゼロクリアされています。
やはりパディング部分がゼロクリアされてないとしか思えないのですが。
よろしくお願いします。



この投稿にコメントする

削除パスワード

No.20864

Re:マルチスレッドの時のmemset
投稿者---おでん(2005/04/29 09:13:11)


>また、パディングされているだろう部分がmemset通過後も
>ゼロクリアされてないのも確認しています。
>でも、それがなぜ、マルチスレッドの時にだけ起きるのか解らないのです。
>
>
>
>
typedef struct  _abc{
    unsigned int a;
    
    unsigned long long b;

    unsigned int c;

    unsigned char d[16];
}ABC;



void abc_init(ABC *abc)
{
    memset(abc,0,sizeof(ABC));
    return; ←(1)
}


int main()
{
    ABC *abc;

    abc = (ABC *)malloc(sizeof(ABC));

    abc_init(abc);

    free(abc); ←(2)

    return 0;
}




自信はありませんが、
「memset通過後」と仰っていますが、具体的には上記のどこでしょう?
環境によると思いますが、もし(1)ならあるかもしれません。
←ディスパッチされた時にはmemset()が完了していない(少なくとも、
メモリに書き込まれていない)・・・かも?
一度、abc_init(abc);の前にmemset(abc,0xff,sizeof(ABC));等を入れて
実際に、どこが風にクリアされていないか確認する必要がありますね?
パディングは、cの上位4バイトになると思います。
・・・確認済みなら申し訳ない。

#通常は、プログラムフローが(ret,jmpなどで)変化する時に
#ディスパッチされることが多いですが

#・・・気持ちが悪いというのはおいといて、
#パディング位置がクリアされないのが何か問題がありますか?


この投稿にコメントする

削除パスワード

No.20865

Re:マルチスレッドの時のmemset(訂正)
投稿者---おでん(2005/04/29 09:16:15)


誤:実際に、どこが風にクリアされていないか確認する必要がありますね?
正:実際に、どこがクリアされていないか確認する必要がありますね?


この投稿にコメントする

削除パスワード

No.20867

Re:マルチスレッドの時のmemset
投稿者---まりー(2005/04/29 09:30:47)


>>また、パディングされているだろう部分がmemset通過後も
>一度、abc_init(abc);の前にmemset(abc,0xff,sizeof(ABC));等を入れて
>実際に、どこが風にクリアされていないか確認する必要がありますね

おお。なるほど。一度、オールFにしてみれば一目瞭然ですね。
試してみます。(現在、旅行中ですので・・・すみません)

>#・・・気持ちが悪いというのはおいといて、
>#パディング位置がクリアされないのが何か問題がありますか?

構造体全体を1つのデータとしてアクセスしたいのです。
パディングがされる以上、メンバの順序を変えるしかないのですが、
なぜそうなるか解らなかったので。



この投稿にコメントする

削除パスワード

No.20868

Re:マルチスレッドの時のmemset
投稿者---REE(2005/04/29 10:29:07)


マルチスレッドの時だけということですが、
具体的に、シングルスレッドの時とどう変えていますか?

ソースは変えずにコンパイルオプションのみなのか、
それともabc_initを別スレッドで起動しているのか・・



この投稿にコメントする

削除パスワード

No.20869

Re:マルチスレッドの時のmemset
投稿者---まりー(2005/04/29 10:42:54)


>ソースは変えずにコンパイルオプションのみなのか、
>それともabc_initを別スレッドで起動しているのか・・

abc_initを別スレッドでいくつか起動させています。


この投稿にコメントする

削除パスワード

No.20870

Re:マルチスレッドの時のmemset
投稿者---REE(2005/04/29 11:10:38)


>>ソースは変えずにコンパイルオプションのみなのか、
>>それともabc_initを別スレッドで起動しているのか・・
>
>abc_initを別スレッドでいくつか起動させています。

別スレッドで起動しているのであれば、
そのスレッドが終了するのを確認してから、結果を表示していますか?
そうでなければ、memsetの処理がまだ終わっていないだけということも考えられます。



この投稿にコメントする

削除パスワード

No.20986

Re:マルチスレッドの時のmemset
投稿者---まりー(2005/05/09 14:35:22)


>別スレッドで起動しているのであれば、
>そのスレッドが終了するのを確認してから、結果を表示していますか?
>そうでなければ、memsetの処理がまだ終わっていないだけということも考えられます。

実際は、abc_initを抜けた後、
sprintfでテンポラリ領域に書き込んでから
表示をするようにしてたので、
memsetの処理は終了していたのではないかと思います。

ですが、、すみません。
カーネルの更新をした所、問題が発生しなくなってしまいました。
構造体中のパディング部分と思われる箇所の
memsetも上手くいくようになりました。

引き続き調査して、原因が解り次第お知らせします。
#元の状態に戻せれば解りやすいのですが・・・。
お騒がせして申し訳ありませんでした。
また、たくさんのお返事ありがとうございました。




この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧