• ベストアンサー

ソート中に生じる変数の値の変化

C言語でソートを用いるプログラムを作成しているのですが,ソートを行った前後で,一部の変数の中身が勝手に書き換えられてしまっています. 例えば,int型で宣言されたix,iy,izという変数の中に格納された値は,ソートには何の関連性をもっていないにも関わらず,ソート後には全て同じ無茶苦茶な値に書き直されます.しかも,何故かこれ等の変数をグローバル変数にした途端に改善されました. ●何故この様な現象が生じてしまったのでしょうか? 加えて,少し類似した症状が,ソートの対象とする構造体にも観察されます.構造体のソートに使う変数自体に変化は見られず,ソート自体も正常に機能していることが確認されているのですが,構造体の他の一部の変数(double型)の値の一部分が0と1072693248に書き換えられます. ●この症状は一体何が原因で,どう改善すれば良いでしょうか? 幾分全く原因が分からない為,質問文自体もかなり曖昧になっていますが,宜しくお願いします.

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.5

ソートと言うからには、構造体の配列をソートしていると思います。 >しかも,何故かこれ等の変数をグローバル変数にした途端に改善されました. >●何故この様な現象が生じてしまったのでしょうか? 多分、ローカル変数の構造体の配列をソートしていると思います。 ソート時に要素数を間違ったり、1要素のサイズを間違ったりすると、構造体の配列よりも後方にある、無関係なローカル変数も「一緒にソート」されてしまいます。 つまりix,iy,izがソートしたい構造体配列の後方にあって「巻き添えでソートされた」のです。 で、ix,iy,izをグローバル変数に変えると、ソートしている構造体配列とは別の離れたメモリ空間に移動するため、ix,iy,izは壊れなくなります(が、代わりに、別の何かが壊れてしまっているでしょう。根本的解決にはなってません) 構造体をソートする際は「構造体1要素の大きさは、足し算で計算してはいけない」「要素の数は定数で書いてはいけない」と言う事に注意しましょう。 例えば、標準関数「qsort」は、 qsort(配列の先頭アドレス,要素数,1要素のバイト数,比較関数) になっています。 ここで typedef struct {   char a;   short b;   int c; /* 比較キー */   char d[15]; } _T_ABC; _T_ABC ary[30]; という構造体配列をソートする時、 qsort(ary,30,sizeof(char)+sizeof(short)+sizeof(int)+sizeof(char)*15,cmp_func); や qsort(ary,30,1+2+4+1*15,cmp_func); と書いたら、メモリを壊します。 intが32ビットの環境では、この構造体は、メモリ上は 1バイト目:a 2バイト目:空き 3バイト目:bの一部 4バイト目:bの一部 5バイト目:cの一部 6バイト目:cの一部 7バイト目:cの一部 8バイト目:cの一部 9~23バイト目:d 24バイト目:空き となっていて、24バイトの大きさがあります。 しかし sizeof(char)+sizeof(short)+sizeof(int)+sizeof(char)*15 の計算結果は 1+2+4+1*15 で、22です。要素のサイズの大きさがウソなのでメモリを壊します。 正しくは qsort(ary,sizeof(ary)/sizeof(_T_ABC),sizeof(_T_ABC),cmp_func); と書かないとなりません。 >●この症状は一体何が原因 ソート作業により、メモリを壊しています。 つまり、余計な所をソートしているか、ソート自体が正しくありません。 >どう改善すれば良いでしょうか? ソート処理のバグを取りましょう。

KennyBR
質問者

お礼

明快な回答有り難う御座いました(´∀`;)ヾ あれ程の少ない情報量の中,明快な回答を提示して下さり有り難う御座います. 御陰様で無事解決しました(´・ω・)ノ

その他の回答 (4)

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

結論から言えばプログラムに誤りがあります。 ソート中にその変数が書き換えられています。 具体的に何が原因かは、ソースを提示していただかないと判断できません。 例えば、以下のようなコーディングは、今回のように、全く関係ない変数を破壊する例です。 char data[10]; char data2[10]; strcpy(data,data2); //data2の中に何が入っているか不定

  • arain
  • ベストアンサー率27% (292/1049)
回答No.3

考えられる一番の理由は、メモリ管理(使用方法)の問題。 配列の宣言要素数を超えてアクセスしたり、小さいサイズの型に大きい当たりを無理に入れたりしようとした場合。 ポインタを使用しているのなら、アクセスしているところが間違っている場合もありえる。

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.2

|●何故この様な現象が生じてしまったのでしょうか? 関数の中に書く変数と、グローバルに使えるようにした変数とでは、メモリに配置する場所が違います。つまり処理が改善されたのではなく、グローバルに置き換えたことで、その変数が影響を受けなくなっただけです。 |●この症状は一体何が原因で,どう改善すれば良いでしょうか? ソースを見せずに言われてもね ^^;) 例えるなら壊れた掃除機を持ってこずに「壊れた、直してくれる?」と言ってるようなもんですよ。

KennyBR
質問者

お礼

>例えるなら壊れた掃除機を持ってこずに「壊れた、直してくれる?」と言ってるようなもんですよ。 ご尤もです(苦笑) つたない質問文にご回答下さり,有り難う御座いました.

  • okg00
  • ベストアンサー率39% (1322/3338)
回答No.1

ソースを見ない限りはなんともいえませんが... ソースを公開してもらえませんか? デバッガを使って変数の動きを追えませんか? 変数はダイナミックですか?スタティックにしてみてはどうでしょうか? >1072693248 これが不定値っぽい気がしますけど。 ポインタを使って別の部分を書き換えていませんか?

関連するQ&A

  • 変数の値が勝手に変化する原因

    以下のようなプログラムを書きました。(一部省略) data2[8] = '\0'; の行が実行された後になぜかgの値が1から0に変化してしまいました。 勝手に変数の値が変化しており、原因が把握できていません。 この原因として考えられることがあれば教えていただけないでしょうか? よろしくお願いします 以下、書いたプログラムです。 char data2[8]; FILE* fp; int g; int main{ fread(data2,8,1,fp); data2[8] = '\0';    ←ここでgの値が変化します。 fread(data2,8,1,fp); data2[8] = '\0'; return 0; }

  • STLのlistのソートについて教えてください。

    STLで何か作ってみようと思っているのですが、複数のメンバを持つ構造体オブジェクトのリスト(要素の値が構造体オブジェクトであるリスト)を、その構造体オブジェクトのメンバの中の1つのをキーとして昇順、又は降順にソートしようとした場合、どのようにすればよいのでしょうか?? http://www5c.biglobe.ne.jp/~ecb/cpp/07_08.html ここを見ると、sort() という関数があるようですが、単に昇順でソートする、としか書いていなく、構造体のリストのソートはどうするのだろうと疑問です。 詳しい方いらっしゃいましたらご教授頂けると幸いです。

  • 参照送りした構造体のメンバ変数の扱い方が

    自作関数に構造体のポインタを送り、メンバ変数の値を扱いたいのですが、 &で送り、*で受け取り、*とアロー演算子でメンバを指定しても 「error C2100: 間接指定演算子 (*) の使い方が正しくありません。」 と出てしまいます。 変数と構造体とでは勝手が違うのでしょうか? どうすればメンバ変数の値を扱えるのでしょうか。

  • 値が変わるのはどうしてでしょうか?

    c言語でプログラミングを行い、コンパイルが通って実行した時に エラーが出たので、1行ずつコンパイルしてみました。 /////////////////ソース部分////////////////////////////// a_save[0] = A[0] //(a_save と A は同じ構造体タグ) a_save[1] = A[1] a_save[2] = A[2] ///////////////////////////////////////////////////////// →ここでコンパイルしたときは当然のように a_save[0].a という変数の値は A[0].a の値と同じ8となっています。 ここからもう少し進んで /////////////////ソース部分////////////////////////////// a_save[0] = A[0] //(a_save と A は同じ構造体タグ) a_save[1] = A[1] a_save[2] = A[2] b[0] = B[0] //(b と B は同じ構造体タグ(Aとは別)) b[1] = B[1] b[2] = B[2] ///////////////////////////////////////////////////////// →ここでコンパイルしたときに A[0].a の値は8のままだったの ですが a_save[0].a の値が急に-858993460というような値に なっていました。 これは何故なのでしょうか?メモリか何かが原因なのでしょうか? よろしくお願いします。

  • 構造体のソートに関して

    VB初心者です。 Private Save() As InIDtyp Private Type InIDtyp ID As String Name As String Unit As String End Type という宣言をしま構造体で値が入っているときにIDをキーとしてソートすることは可能でしょうか。 1回やってみたのですが、IDのみソートされてしまい、NameとUnitは一緒にソートされずにそのまま残ってしまいました。 デバッグをかけて中を見ましたらこんな感じでした。 例: 元の構造体 Save(0) ------ID:  56 ------Name: AA ------Unit: ms Save(1) ------ID:  35 ------Name: KY ------Unit: yy Save(2) -----ID:  33 ------Name: LI ------Unit: ba ソート後 Save(0) -----ID:  33 ------Name: AA ------Unit: ms Save(1) -----ID:  35 ------Name: KY ------Unit: yy Save(2) -----ID:  56 ------Name: LI ------Unit: ba どなたか構造体のソートのやり方をご存知の方がいましたらご教授お願いします。

  • C,C++,Javaの変数の種類

    クラス、構造体の変数の中で外部からアクセスできないという設定があります。アクセスできないというのは、 0.値を見ることができるが変更はできない(定数のような感じ? 消費税率とか?) 1.値を見ることはできないが変更することはできる(銀行預金額面風?) 2.値を見ることも変更することもできない (どう利用するのでしょうか?) にわかれるように思います。もし2ならば、その変数は構造体、クラスの外部に影響を与えないように思います。すなわちそのような変数の使用が何を目的としているか不明になるように思いますが。 例えば、Xを2の意味で隠蔽していたとします。 Yを与えて、Z=Y*Xを計算し、Zの値を取り出すと、Xの値が間接的にわかることになります。これだと変数を隠蔽したことならないのでこのような使い方もエラーになるだろうと思いますが。 すなわち、アクセスできないとはどういう意味になるのでしょうか。 C,C++,Javaを同時に見ており、private, staticなどいろいろあって混乱してしまいました。 変数のアクセス制限・隠蔽についてどのように整理すればよろしいでしょうか。 よろしくお願いします。

  • 構造体の変数の値を、動的に取得する方法を教えてください

    C言語で、構造体の変数の値を取得したいのですが、その際、 他の変数に格納してある文字列を元に動的に行いたいのですが、可能でしょうか? イメージとしては、 struct Entry{ char name[20]; char address[80]; char email[40]; }; struct Entry data; strcpy(data.name, "Taro"); strcpy(data.address, "Tokyo"); strcpy(data.email, "taro@taro"); char var_name[20]; strcpy(var_name, "email"); printf("%s", data.var_name); ↑この行の構造体の変数へのアクセス方法が間違っているのはわかっていますが、このような時に「taro@taro」と出力させたいのです。 var_nameの値を「name, address, email」に換える事により「Taro, Tokyo, taro@taro」と出力を切り換えたいと思っています。 普段は他の言語をよく使用しており、そちらではこの手法を時々使っていたのですが、C言語でも出来ないものかと思っております。 よろしくお願いします。

  • 構造体配列のクイックソート

    こんにちわ。 構造体配列のリストを ポインタのつなぎ変えによるクイックソートで 以下のようなソートをしたいのですが、悩んでおります。 struct info { int count; struct info *prev; struct info *next; }; int main () { struct info info[5]; /* 初期値設定 */ quick_sort(info, 0, 5); return 0; } 上記のようにして、クイックソートをしたいのですが、 よくあるクイックソートだと 例えば初期値を <配列のindex>要素の値を <0> <1> <2> <3> <4> 5 1 4 3 2 などと定義した場合 普通のクイックソートだと <0> <1> <2> <3> <4> 1 2 3 4 5 というように並び変えられてしまい <配列のindex>と 要素の値の組み合わせが変わってしまいますが、 この組み合わせを変えず、 struct info *if; if = info; for (i=0; i<MAX; i++){ printf("%d", if->count); if = if->next; } printf("\n"); とすることで、indexとしては昇順になっていないが *nextをたどっていくことでちゃんと目的の値の昇順になっている というのを実現したいのですが、ポインタのつなぎ変えか何かが 間違っているようで うまいことできていません。 どなたかご教授いただけますでしょうか。 申し訳ありませんが、よろしウお願いいたします。

  • DLLで格納された値をVBに渡す方法

    <VC++で作成したDLLをVBで呼ぶ処理> VBから変数をDLLに渡して値を格納してVBで受け取りたいのですが、 文字列が格納されている先頭アドレスをVBに渡したい場合の 方法を具体的に教えてください。 構造体を使用する方法はできたのですが、使わない方法(引数が変数)を 教えてください。 よろしくお願いします。

  • セグメンテーション違反

    C言語を使用しています。 構造体に値をいれようとしたら、コンパイルは出来るのですが、実行時に 「セグメンテーション違反です (core dumped)」 となってしまい、それ以上行えません。 構造体と代入したい変数との型は、合っています。 いろいろ本などで見ましたが、何が原因かわからず困っています。 教えてください。 宜しくお願いします。

専門家に質問してみよう