コンストラクタ内での動的メモリ割り当ての対処

このQ&Aのポイント
  • VS.NET2003でC++を使いプログラミングをしています。コンストラクタ内で、動的にメモリを割り当てたクラスを何度も生成すると動きがおかしくなるようなんです。
  • メモリブロックでのエラーがでたり、アプリがフリーズします。newで動的に割り当て、va_startマクロを使って値を代入しています。
  • 二重解放にならないように、関数内でdeleteしたptにNULLを代入させ、ifを使って弾くようにしているんですが、それでも万全ではないのでしょうか?フリーズしたりメモリブロックでエラーを起こしたりする原因が分からない状態です。
回答を見る
  • ベストアンサー

コンストラクタ内での動的メモリ割り当ての対処

  こんにちは。    VS.NET2003でC++を使いプログラミングをしています。   コンストラクタ内で、動的にメモリを割り当てたクラスを何度も生成すると動きがおかしくなるようなんです。   メモリブロックでのエラーがでたり、アプリがフリーズします。   以下はそのクラスのコンストラクタのコードです。 ClassA::ClassA(double x, double y, WORD tm, WORD len, WORD rat, ...) : CBullet(x, y, 0, 0, 0, 0, 20), LT(tm), Tp(rat), Len(len), Tc(0), pt(NULL) { pt = new WORD[rat]; va_start( list, rat ); for(WORD i = 0; i < rat; i++) { pt[i] = va_arg(list, WORD); } va_end(list); }  new で動的に割り当て、va_startマクロを使って値を代入しています。  二重解放にならないように、関数内でdeleteしたptにNULLを代入させ、ifを使って弾くようにしているんですが、それでも万全ではないのでしょうか?  フリーズしたりメモリブロックでエラーを起こしたりする原因が分からない状態です。   よろしくお願いします。

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

プログラムがこの通りなら (コピーコンストラクタが private なので) 引数 (と返り値) がらみの話はないようですね>#2. とはいえやはり「メモリ管理がなにかおかしい」感じはあるので, std::vector などを使って「なるべく自分では管理しない」という方針は考えられますな. 代入でこけるとか, そういう腐ったネタだったりする? あと, 「WORD が int より短いとアウト」というのは「可変引数を持つ関数に実引数をどのように渡すか」に由来します. 「(signed/unsigned を含む) char と (unsigned を含む) short」は (signed あるいは unsigned の) int に, また float は double に, それぞれ自動的に変換されます. 一方, va_arg の方はそんな事情などおかまいなしに指定された型と思って値を取り出そうとします. つまり, 今の場合 「int で渡された引数を WORD で取り出す」ことになってしまい, sizeof(WORD) < sizeof(int) だと正しい値を取り出すことができなくなってしまいます. 実際, pt[i] を表示させると期待した結果にはなっていないはずです. もっとも, 「va_list をクラスメンバにする」理由がさっぱり思い付きませんが. こいつをメンバにしてうれしいことなど全くないとしか思えない.

DEADSPACE566
質問者

お礼

  なるほど。 マクロではint型で割り当てられているという事でしょうか? >もっとも, 「va_list をクラスメンバにする」理由がさっぱり思い付きませんが. こいつをメンバにしてうれしいことなど全くないとしか思えない.  なるほど、勉強になりますね。 va_listをクラスメンバにせず別の方法を使うんでしょうか? 全くない理由を言って頂ければとてもありがたいです。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

「今まで作る必要がなかったからデストラクタを作らない」て.... どんな理屈だ, それは. 「今まで」がどうであろうと, このクラスは「このクラス」でしょ? だとしたら「今まで」とは無関係に「このクラスで必要かどうか」を考えるべきだし, インスタンスを 1個しか作らないことが保証できるならともかくそうでなければ「コンストラクタでメモリを確保する以上デストラクタで解放する」というのは (完全に「絶対」ではないけど) ごく普通だよ. なぜ何度も「std::vector」と言い続けているのか, その理由はわかりますか?

DEADSPACE566
質問者

お礼

そのクラスには親を継承させているので、その状態でデストラクタを呼ぶ場合についてあまり把握していなかったので、あまり追加しようとは思っていませんでした。  たださっき動かしてみたんですが、ちゃんとデストラクタは呼ばれているみたいなんでここで解放処理をしてみようと考えています。  ちょうどコンストラクタ内での動的割り当てでの対処ができたのでそれでいこうと思います。  std::vectorはまだ使った事がないのであまり把握していません。 ただ今まで読んできたあたり、vectorは可変長配列で、解放などの後処理をちゃんとサポートしてくれる。 という感じです。  なのでその辺の反応は鈍いです。

DEADSPACE566
質問者

補足

  あれから暫く調べてみたんですが、今のところスマートポインタでは駄目なんだなぁというところまで来ています。   catch & tryでコンストラクタで保護→ガチガチに固めるならスマートポインタがいい→しかしスマートポインタは配列管理ができない。 なん・・・だと・・・ ←今ここ

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

まず va_list については「当該関数が動いていなければ意味のない値」ですから, これをクラスのメンバにする意味は全くありません. 関数のローカル変数にすれば十分. たとえば, 最初の質問に挙がっているコンストラクタでも変数 i はメンバにしてませんよね. これと同レベルの話です. むしろ, 「なぜ va_list をクラスのメンバにしたのか」の方を聞きたい. で「マクロではint型で割り当てられているという事でしょうか?」については何を聞いているのかが分かりません. 単純に*言語仕様*として「可変長引数として渡した (int より短い) 実引数は必ず int (か unsigned int) に変換される」というだけであり, ここにはマクロは関係ありません. 本題については, 何度か書いてるけど ・std::vector を使う ・代入演算子とデストラクタを適切に宣言 (and/or 定義) する あたり? 現状コピーはできないのでコンパイルエラーがなければあえてコピーコンストラクタを定義する必要はないと思いますが, 特に代入演算子が宣言されていないために「メンバごとの代入」をする代入演算子が自動的に作られている可能性がなきにしもあらず. あと, なんでデストラクタを作らない?

DEADSPACE566
質問者

お礼

  回答ありがとうございます。 上のva_listの理由とWORDとshortの問題は理解できました。 ・代入演算子とデストラクタを適切に宣言 (and/or 定義) する という方針を採ってみようと思います

DEADSPACE566
質問者

補足

  デストラクタを作らないのは今まで作る必要がなかったからです。 動的に割り当てて動かすクラスは滅多にないので。   でもデストラクタ内で解放処理を行った方がいいんでしょうか? コピーコンストラクタについてもう少し勉強してみようと思います。

回答No.4

他のひともいってますが、このコンストラクタ自身に問題はないように思います。 sakuraエディタでも何でもいいから、ClassAを生成している行をピックアップして ratの値が嘘ついていないことを確認して、問題なければ pt に アクセスしている部分に片っ端からassert()を仕込んでみたらどうですか。

DEADSPACE566
質問者

お礼

>ptに アクセスしている部分に片っ端からassert()を仕込んでみたらどうですか。 assertでそのアクセスしている部分がNULLでないか?を調べるということでしょうか?

回答No.2

 「class Aのオブジェクトを関数の実引数にしていて、その関数の対応する仮引数が参照型でない」ということはありませんか。この場合、関数が引用されたとき、仮引数のオブジェクトが作られて実引数のメンバ変数の値がコピーされます。関数の終了時に仮引数オブジェクトのディストラクタが呼び出されますが、その中にdeleteがあると、実引数のオブジェクトが確保したメモリが解放されてしまいます。ディストラクタの中でポインタをNULLにしても、実引数のオブジェクトには反映されません。  関数の仮引数を参照型にするか、コピーコンストラクタを作ってディープコピーを行うようにすれば回避できます。

DEADSPACE566
質問者

お礼

 コピーコンストラクタを作ってディープコピーをするんですね?  やってみます。

DEADSPACE566
質問者

補足

 NULLを代入しているのはクラスのメソッドの中です。解放しているのもそのメソッドの中です。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ん~, これだけしか情報がないと分かんないなぁ. 「メモリブロックでのエラー」が何を意味しているのか分からないし, WORD が本当に正しいのかどうかも不明 (WORD が int より短いとアウト). あと, 「list」の定義がないのはなぜ? あるいは, new を使って自前でメモリを管理する代わりに std::vector を使ったらどうなるんだろう.

DEADSPACE566
質問者

お礼

listがなんであるのか下記のコードを載せておきます。 クラス内のメンバ変数で、マクロです。 class ClassA : public Class { double SPD; WORD Tp, Tc, LT, Len; WORD *pt; va_list list;//va_listというマクロです。 private: ClassA(const ClassA &src); public: ClassA(double x, double y, WORD tm, WORD l en, WORD rat, ...); }; メモリブロックのエラーはWORD* ptでの二重解放で起きたことがあるんですが、他の箇所にもでてきてるようです。

DEADSPACE566
質問者

補足

>WORD が本当に正しいのかどうかも不明 (WORD が int より短いとアウト). とはどういうことなんでしょうか?  WORDはunsigned shortで、intより短いです。  これに何か原因があるのでしょうか?

関連するQ&A

  • メモリとポインタと配列と

    malloc()を使用して可変の変数を作り加工。 後々に参照するためにポインタの配列に格納したいと考えております。 malloc()を行った後は必ずfree()にてメモリを開放せねばなりませんが、開放するとポインタの配列に格納した値も消えてしまいます。 だからといって開放せずにいるとメモリリークが起きてしまいます。 この様な場合はどのようにすればよろしいのでしょうか? 大体以下のような処理を考えております。 ご教授願えれば幸いです。 ****************************************   char *p[100];   for(int i=0;i<100;i++) {     char *word1 = "あいう";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     int size = strlen(word1) + 1;     char *memo1 = (char *)malloc(size);     if (memo1 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     strcpy(memo1, word1);          //・     //・ *memo1 を利用した処理。     //・     char *word2 = "abc";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     size = strlen(word1) + 1 + strlen(word2) +1;     char *memo2 = (char *)malloc(size);     if (memo2 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     memset(memo2, 0x00, size); //初期化     strcpy(memo2, word2);     strcat(memo2, "\t");     strcat(memo2, memo1);     p[i] = NULL;     p[i] = memo2;     free(memo2);     free(memo1);   } **************************************** 宜しくお願いします。

  • 構造体へのポインタ

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の 他の関数内での使用の仕方が全くわかりません。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list {  char keyword[MAX_KW_LEN];  struct list *next;   /* 次の list へのポインタ */ }; struct list *hashtable[HASHSIZE]; /* ハッシュテーブル */ /* キーワード ( Cの予約語 ) */ static char kw[NUM_KW][MAX_KW_LEN] = {   "auto", "break", "double",   "enum", "char", "continue", "extern", "float", "for", "int",   "long", "register", "short", "signed", "static",   "struct", "typedef", "union", "unsigned", "return",   "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) {  int hashval = 0;  while (*key != '\0')   hashval += *key++;  return (hashval % HASHSIZE); } void InitHTable(void) {  int i;  struct list *p, *q;  int hashval;  for (i = 0; i < NUM_KW; i++) {   printf("%d\n",i);   if ((FindKeyWord(kw[i])) == FALSE) { /* 登録されていなかったら */             /* メモリを割り付ける */    if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) {     fprintf(stderr, "メモリ不足です。\n");     exit(2);    }    strcpy((*p).keyword, kw[i]);    hashval = Hash(kw[i]);    /* ハッシュ値を求めて */        if (hashtable[hashval] == NULL) { /* 未登録なら */     hashtable[hashval] = p;  /* p の指すアドレスを登録 */     p->next = NULL;    /* リストの末尾に NULL を追加 */    }    else {        /* 既に登録していたら */     q = hashtable[hashval];     while (q->next != NULL) {  /* データがなくなるまで */      q = q->next;    /* リストをたどる */     }     q->next = p;     /* リストの末尾に p の指すアドレスを登録 */     p->next = NULL;    /* その末尾に NULL を追加 */    }   }  } } int FindKeyWord(char *key) {  struct list *p;  for (p = hashtable[Hash(key)]; p != NULL; p = p->next)   if (!strcmp(key, (*p).keyword))  /* 登録済みなら */    return (TRUE);     /* TRUE を返す */   return (FALSE);      /* 未登録ならFALSE を返す */ } void ListKeyWord(void) {  int i;  struct list *p;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; p = p->next) /* p が NULL でなければ */               /* ハッシュ値とキーワードを表示 */    printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } /* malloc( ) で割り付けたメモリを解放 */ void FreeKeyWord(void) {  int i;  struct list *p, *q;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; ) { /* p が NULL でなければ */    q = p->next;      /* p->next を保存 */    free(p);       /* メモリを解放 */    p = q;        /* p->next を p に代入 */   } } int main(void) {  char word[MAX_KW_LEN];  int i;  InitHTable( );  ListKeyWord( );  for (i = 0; i < 4; i++) {   printf("Cの予約語を入力して下さい ");   fgets(word, 128, stdin);   if ((FindKeyWord(word)) == TRUE)    printf("%s は登録済みです。\n", word);   else    printf("%s は未登録です。\n", word);  }  FreeKeyWord( ); }

  • コンストラクタやデストラクタと例外について

    対処法が「概念的に」書かれているサイトや書籍は結構あるようなのですが、具体的なコードでビシッと書かれてることや、そもそも根本的に「どういう場合に例外が発生するのか」の、帰納的な説明はなかなか見つからないので、もやもやしています。 また、「人が書いたコードを使う場合に全部読んでられないような状況」という前提が暗黙にあって書かれている文章が多いと感じます。 しかし、根本的なところが分からないともやもや感は拭えません。 1.もし仮に自分が全てのコードを把握し、「コーディングの段階で明白に消せる例外の可能性」を、あらかじめ消しておける(さすがにnewなどC++の標準的機能は使用し)とした場合は 自分自身で例外をthrowするか、メモリ不足でbad_allocになる以外にコンストラクタ(あるいはデストラクタ)でcatch出来るような例外が発生する可能性はあるのでしょうか? そして例えば以下のように書いたとします。(必要なヘッダ等は省略してあります) ///////////////////ヘッダ側//////////////////////// class A{ double d; public: A(double a=0) : d(a) {} ~A(void){} }; class B{ std::auto_ptr<A> p; A *alist[10]; public: B(void); ~B(void); }; ///////////////////こちらがソースです//////////////////////// B::B(void) try { memset(&alist,0,sizeof alist); std::auto_ptr<A> ap( new A(.8) ); p=ap; for ( int i=10;i; ) alist[--i]=new A; } catch(std::bad_alloc){ for ( int i=10;i; ) delete alist[--i]; } catch(...) { /*......*/ } B::~B(void){ try{ for ( int i=10;i; ) delete alist[--i]; }catch(...){} } こうしたとすると 2.このコードはコンストラクタ中で例外が発生した場合、コンストラクタなので「呼ばれることになった原因の場所へ自動的に例外が再度投げられる」という点を除けば、安全でしょうか? 3.そもそもコンストラクタで例外が発生した場合、呼び出し元に届くように「自動的に、あるいは手動で」投げなければ「ならない」のでしょうか? 4. 1とかぶりますが「このコードの場合に限定」していうと、catch(std::bad_alloc)の後ろに書いたように、果たしてcatch(...)は必要なのでしょうか? つまりstd::bad_alloc以外の例外が発生する可能性はありますか? 5.このコードの場合では、このようにデストラクタをtryブロックで囲う必要は事実上ないと考えて良いですか? 6.また、もしclass Aのデストラクタを見ることができないという場合は、逆に囲うべき、という意味なのでしょうか? 7.auto_ptrのかわりに通常のポインタを使う場合 ポインタの配列alistと同じように、先にNULLにしておいてからnewして、catch(std::bad_alloc)に入った場合は delete ポインタ。 例外が発生しなかった場合デストラクタのほうにも解放処理はちゃんと書く、としていれば、この場合大丈夫でしょうか?

  • C言語のプログラム

    以下のプログラムはハッシュテーブルを用いて文字列を探すプログラムなのですが、コンパイル時にセグメントエラーとなってしまいます。プログラム中に誤った箇所があれば教えて頂きたいです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 10 #define MAX_LEN 64 #define N_WORDS 4 struct list { char word [MAX_LEN]; struct list *next; }; struct list *hash_table[HASHSIZE]; char colors[N_WORDS][MAX_LEN] = {"red", "blue", "green", "yellow"}; void my_strcpy(char* a, const char* b) { int i = 0; while(*b != '\0'){ *(a+i) = *(b+i); i++; } *(a+i) = '\0'; } int hash(char *key) { int hashval = 0; while (*key != '\0') { hashval += *key; key++; } return (hashval % HASHSIZE); } int find_word (char *key) { struct list *p; for (p = hash_table[hash(key)]; p != NULL; p++) if (strcmp(key, p->word) == 0) return 1; return 0; } void init_hash_table() { int i, hashvalue; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) { hash_table[i] = NULL; } for (i = 0; i < N_WORDS; i++) { if ((find_word(colors[i])) == 0){ p = (struct list *)malloc(sizeof(struct list)); my_strcpy(p->word, colors[i]); hashvalue = hash(colors[i]); if (hash_table[hashvalue] = NULL) { hash_table[hashvalue] = p; p->next=NULL; } else { q = hash_table[hashvalue]; while (q->next != NULL) q = q->next; q->next = p; p->next=NULL; } } } } void main(void) { init_hash_table(); printf("result = %d\n", find_word("red")); }

  • 動的なメモリ領域の確保

    double型変数5個分のメモリをmalloc関数により確保し,その確保した要素のアドレスを表示するように,プログラムを作る問題で、 (注)に「 %pで表示するためには,double型へのポインタ(double *)をvoid型へのポインタ(void *)にキャストする必要がある.」と書かれていたのですが、どういうことでしょうか? 以下のようでいいのでしょうか? #include<stdio.h> #include<stdlib.h> #define COUNT 5           // 動的に確保するメモリ領域数を示すマクロ定数の定義 int main(void) {  // 動的に確保するメモリ領域のアドレスを保持するポインタ変数の宣言  double * pointer;  int i;                  // for文で使用する変数の宣言  // int型変数5個分のメモリ領域を確保  pointer = (double *)malloc(sizeof(double) * COUNT);  if(pointer == NULL) {        // メモリ領域の確保が失敗した場合   printf("メモリ領域を確保できませんでした.\n");   exit(1);                // プログラムの終了  }  for(i = 0; i < COUNT; i++)   printf("%d番目のアドレスは%pです.\n", i + 1, pointer + i);  free(pointer);            // 確保したメモリ領域の解放  return 0; }

  • ポインタの扱い

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の処理がうまくいきません。。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list { char keyword[MAX_KW_LEN]; struct list *next; }; struct list *hashtable[HASHSIZE]; static char kw[NUM_KW][MAX_KW_LEN] = { "auto", "break", "double", "enum", "char", "continue", "extern", "float", "for", "int", "long", "register", "short", "signed", "static", "struct", "typedef", "union", "unsigned", "return", "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) { int hashval = 0; while (*key != '\0') hashval += *key++; return (hashval % HASHSIZE); } void InitHTable(void) { int i; struct list *p, *q; int hashval; for (i = 0; i < NUM_KW; i++) { printf("%d\n",i); if ((FindKeyWord(kw[i])) == FALSE) { if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) { fprintf(stderr, "メモリ不足です。\n"); exit(2); } strcpy((*p).keyword, kw[i]); hashval = Hash(kw[i]); if (hashtable[hashval] == NULL) { hashtable[hashval] = p; p->next = NULL; } else { q = hashtable[hashval]; while (q->next != NULL) { q = q->next; } q->next = p; p->next = NULL; } } } } int FindKeyWord(char *key) { struct list *p; for (p = hashtable[Hash(key)]; p != NULL; p = p->next) if (!strcmp(key, (*p).keyword)) return (TRUE); return (FALSE); } void ListKeyWord(void) { int i; struct list *p; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; p = p->next) printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } void FreeKeyWord(void) { int i; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; ) { q = p->next; free(p); p = q; } } int main(void) { char word[MAX_KW_LEN]; int i; InitHTable( ); ListKeyWord( ); for (i = 0; i < 4; i++) { printf("Cの予約語を入力して下さい "); fgets(word, 128, stdin); if ((FindKeyWord(word)) == TRUE) printf("%s は登録済みです。\n", word); else printf("%s は未登録です。\n", word); } FreeKeyWord( ); }

  • TList->Clear();でメモリ解放不可

    C++Builder5を使っています。 TListの使い方で質問します。 List->Clear();で、Listのために使っていたメモリーも解放されるものと思っていました。 ところが、タスクマネージャでのメモリー使用量を見ているとそうなっていないようです。 Form上にあるボタンを押した時に次のような処理を記述しました。 UkeML->Clear(); for(i=0;i<800000;i++){ pt = new UkeM; strcpy(pt->t,tx); UkeML->Add(pt); } ボタンを何回押しても同じ事が繰り返される、と思ったのですが、私の環境では4回目まで(320万回)はOKですが、5回目でエラーとなります。 私の利用環境において、1回の起動で、ノードの追加が累積100万回を超える事はほぼ考えられないのですが、絶対にない、とは言い切れないので何とかしたいと思っています。 2回目以降で新規のListを作ろうとする時に、それまでのメモリーを解放するためには、どうしたら良いでしょうか? アドバイスいただければ、と思います。 ちなみに私の環境は、 Win7 Pro 64bit メモリ4Gです。 メモリ8GのPCでも同じ現象でした。

  • 配列の中に、リストが入っているものをボトムアップ形式でマージソートして

    配列の中に、リストが入っているものをボトムアップ形式でマージソートしています。 リストは、空のノードの次に文字列が入ったノード、というものです。 sizeは、配列の要素数となっています。 merge_listは、リスト2つをマージするものです。 2つのリストをマージして、ひとつになったリストを最初のリストが入っていた配列に入れる。 もう片方はNULLにする。 順に繰り返していき、配列の要素が1つのみになったらそれを返す・・・ といったアルゴリズムなのですが、うまく配列の中のリストが指定できません。 調べたところ、おそらくプログラム中の矢印があるところに問題があってprintfが実行できないようなんですが、原因がわかりません。 同じ原因によりmerge_listに、マージしたいリストが入っていないようなんですが・・・。 説明下手ですいませんが、どうかよろしくお願いします。 typedef struct list * word_list; struct list { char* word; word_list rest; }; word_list _mergesort(word_list* word_lists, int size) { int i=0, j; while(1){ while(1){ while(word_lists[i] =NULL) //配列に一つ目の要素が見つかるまで回す <- 原因 i++; j = i+1; while(word_lists[j] =NULL) //配列に二つ目の要素が見つかるまで回す<- 原因   j++;       if(j == size) //マージする要素が後ろになかったら終了  break; //printf("%d,%d\n",i, j); printf("%s\n",word_lists[i] ->rest ->word);  <-ここでエラー printf("%s\n",word_lists[j] ->rest ->word); word_lists[i] =merge_list(word_lists[i], word_lists[j]); word_lists[j] =NULL; printf("%s",word_lists[i]->rest ->word); i = j+1; } if(i !=0){ i = 0; }else{ break;    //要素がひとつしかなかったら終了 } } return word_lists[0]; }

  • 領域を確保した後の文字の並び替え

    領域を確保した後、アドレスを書き変える勉強をしています。入力した文字を逆から表示していくことに成功したので今度はソートで小さい順に並び替えをさせようとしまして、色々試したのですが何度やっても上手くいきません。 どのように組めばいいか教えてください。よろしくお願いします。 #include<stdio.h> #define MAX 40 struct parts * ListChar(char moji[]); typedef struct parts{ struct parts *next; char moji; }PARTS; main(void){ char moji[MAX]; PARTS *list; PARTS *head; scanf("%s",moji); head = ListChar(moji); for(list=head ; list!=NULL ; list=list->next){ printf("%c",list->moji); } printf("\n"); for(list=head ; head!=NULL ; list=head){ head = list->next; free(list); } } struct parts * ListChar(char moji[]){ int i,j,len1; char dam; PARTS *head; PARTS *list; PARTS *back; PARTS *start; PARTS *list2; len1 = strlen(moji); for(i=0 ; i<len1 ; i++){ list = (struct parts *)malloc(sizeof(struct parts)); /*領域の確保*/ list->next = NULL; if(i == 0){ head =list; }else{ back->next =list; } back = list; list->moji = moji[i]; } head = back; return head; }

  • USBメモリを指していると、OSが起動できない

    現在、「SOTECのPC STATION PT852」のPCを使用しています。 このPCで、USBメモリを指している状態だとOSが起動できません。 USBメモリを外せば、OSは起動します。 ポートが壊れているのかと思い全部のポートで確かめましたが、 指している状態だと全く起動しません。 プリンターや外付けHDDなどは、ポートに指している状態でも起動できます。ポート自体は壊れていないです。 USBメモリを指している状態でもOSを起動させたいのですが、 どのように設定したらできるのでしょうか? PCのスペック メーカー:SOTEC 型番:PC STATION PT852 OS:Microsoft Windows XP Home Edition CPU:AMD AthIon(tm)64 Processor 3200+,MMX,3DNow,~2.0GHz メモリ:1022MB RAM SOTECの「PC STATION PT852」のサイト ​http://support.sotec.jp/pds/manual_list.asp?pc=0300260000011 SOTECのサポートセンターに聞こうと思ったのですが、購入から1年経っているとサポートしてくれないので質問させてもらいました。 よろしくお願いします。