• 締切済み

ポインタ&mallocで困っています(C言語)

あるローカル関数内でポインタを宣言し、mallocで領域確保します。そのポインタをグローバルで宣言したポインタに渡します。そしてローカル関数を抜ける。 その後、他のローカル関数内で、そのグローバルなポインタを呼び出して、ポインタの実態を参照しているのですが、プログラムが進むうちにそのグローバルポインタの実態の一部が書き換わってしまいます。どういう原因が考えられるでしょうか?

みんなの回答

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

solaris 8 デバッガはdbxという前提です。 使用されているのが、このデバッガでない場合は、以下の文章は参考になりませんが・・・・ stop accessを使用します。 stop access モード アドレス[,サイズ] モードはr,w,x等があります。 アドレスは、直接番地を指定することもできます。 例 char data[256]のdata[8]が更新された時、停止する。 stop access w &data[8] 詳細はdbxのマニュアルを参照下さい

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.1

意図しないところで、プログラムがそのポインター又はポインターの示す先を破壊しています。通常、この現象が発生するのは、メモリの転送命令を使用した場合です。以下の命令で破壊する可能性があります。 memcpy(転送先のアドレスの誤り、転送サイズの誤り) strcpy,strncpy(転送先のアドレスの誤り、転送元が終端NULLになっていない) printf,sprintf,fprint(引数の数と書式が合っていない、引数と書式が合っていない) 等を再調査してみて下さい。 どの環境で実行されているかが判りませんが、通常はデバッガで「指定されたメモリの内容が変更された場合、そこで停止する」指示をすることができます。破壊されるメモリの場所が判っていれば、その指示を行うことによりどのステートメントで破壊しているかが調査出来ます。

taurus4
質問者

お礼

原因が分かりました。 配列を10万個しか宣言していなかったのに、10万以上の配列に値を入れた際に、書き換えられてしまっていました。 やはり、数が未定の値は、はじめにこのくらいだろうと、決め付けずにそのつどmallocをするべきでした。 単純なミスですみませんでした。

taurus4
質問者

補足

ありがとうございます。調べてみたいと思います。 それと、お聞きしたいのですが >破壊されるメモリの場所が判っていれば、その指示を行うことによりどのステートメントで破壊しているかが調査出来ます。 とありますが、どのように記述すればよいのでしょう? OSはSlarisというやつです。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

  • mallocの書式について

    初心者です。プログラム上でメモリを確保するmallocという関数がありますが書式がいまいち良くわかりません・・。   戻り値? * malloc(確保する型 * 確保する数) のように書いてますけどmallocの前のはやはり戻り値?そのまえの*は?いまいちわかりません。よろしくお願いします。

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

    char *name この宣言でプログラムの組初めはこれでいけたのですが char *name = (char *)malloc(sizeof(char) * 10); 後からこのようにmallocで動的メモリ確保しないとセグメンテーション違反が起きるようになりました。 なぜこうなるのでしょうか? それとmallocの使うタイミング(どういう時)に使えばよいのでしょうか?

  • malloc領域から関数ポインタ型で呼び出し

    現在C言語で,関数ポインタ型による関数の呼び出しを勉強しています. print()という関数は受け取った文字列を表示するだけの関数ですが, これを通常の関数ポインタを用いて実行したのがmain内の(*mem)("FROM POINTER.");です. これに対して後半は,mallocで確保した領域にmemcpyでprint()をコピーし, (*mem)("FROM COPIED AREA.");で実行しています. 実行環境は以下の通りです. OS:Windows7 Personal 32bit CPU:Intel Core i5 M430 統合開発環境:Visual C++ 2010 Express Edition コンパイルには成功しています. 実行すると"FROM POINTER."は表示されるのですが, "FROM COPIED AREA."は表示されず,プログラムが動作を停止してしまいます. mem = (void (*)(char*))tmp;までは実行できているようですが, (*mem)("FROM COPIED AREA.");の実行の時点で停止しているようです. またコマンドプロンプトからBorland C++ 5.5.1でコンパイルしても, 同じように動作が停止してしまいます. ただし同じプログラムでも,Cygwinからgccでコンパイルすると, 意図した通りの挙動となっていることを確認しています. コンパイラの違いによるものなのか, UNIXとWindowsの違いによるものなのか判断できずにいます. (もしくはライブラリのmalloc,memcpy辺りの実装法の違いでしょうか?) どなたかご存知でしょうか. ----------------------------------------- #include<stdio.h> #include<stdlib.h> #include<string.h> #define SIZE 512 void print(char* str){ printf("%s\n", str); } int main(int argc, char** argv){ void (*mem)(char*); void *tmp; mem = &print; (*mem)("FROM POINTER."); tmp = malloc(SIZE); memcpy(tmp, print, SIZE); mem = (void (*)(char*))tmp; (*mem)("FROM COPIED AREA."); }

  • 配列ポインタの関数中のメモリ領域

    C初心者です。 関数中で配列ポインタを宣言する場合についての質問です。 たとえばDouble型の2次元のローカルな配列ポインタを用いる場合、 その配列要素数が100である場合は void 関数名(引数1,引数2,...){ int i; double *a[2]; for(i=0;i<2;i++){ a[i] = (double*)malloc(100*sizeof(double)); } for(i=0;i<2;i++){ free(a[i]); } } またこの値を引数1とする場合、引数1をoutとすると void 関数名(double *out,....) とし、 for(i=0;i<2;i++){ out[i] = a[i]; } とすればよいのでしょうか? もしこれがあっているとすると、つぎのような現象で困っています。 配列要素数を50000個ぐらいとし、複数の関数で、同様に mallocを用いて、配列ポインタのローカルでメモリ領域を確保しようとした場合、コンパイルは成功するのですが、その後実行すると、エラーが発生したというメッセージとともにコマンドウィンドが強制終了します。 コンパイラはVisual C++ EXpress Edition 2008です。 データサイズを小さくすると、エラーは起きません。 malloc関数で確保するメモリサイズは、関数の入力引数で定義された変数を用いて計算しており、データサイズに応じて変更されます。 よろしくお願いいたします。

  • ポインタのポインタの初期化法

     文字列をポインタを使って扱うとき、例えば、初期化は次のように行えますよね。 #include <stdlib.h> char *s; s = (char *)malloc(1000); (これに続いてscanf("%s", s);など)  これと同様にして、二次元の配列を、ポインタのポインタを使って表したいとき、 char **s; と宣言したものを、malloc()関数を使って初期化することはできるのでしょうか。よろしくお願いします。

  • C言語のメモリ領域確保

    ポインタ変数ををmain関数で宣言し、関数test()にて必要分だけ領域確保してそのアドレスをmain関数のポインタ変数に渡して利用することは可能でしょうか。 (サイズのわからないテキストデータを、十分に大きな配列に入れるのではなく、関数でメモリを動的確保して無駄の無い配列に入れたい等) C言語ではやはり無理で、構造体のリストにするのが一番でしょうか。 初歩的なことで申し訳ありませんがどなたかお願いいたします。

  • C言語のソースコードからどのようにメモリ領域を使用しているのかを図で説明してくれるソフト

    私はプログラミング初心者なのですが、以前プログラミングについて詳しい方に、どのようにしたら他の方が作成されたプログラムを解析していったら良いのかということを相談したところ、まずプログラムで宣言されているポインタなどの使い方などから、メモリ領域の使い方を読み取り、それを図にまとめるなどしてメモしていった方が良いという助言をいただきました。 いろいろとポインタなどについて参考になるWEBサイトなどを参照していったのですが、ポインタの書き方などが様々なものがあるということを知り、困っています。ただ、eeprom領域のメモリを電源を入れた際にCPUがそれをSRAM領域に呼び出して、関数がそのSRAMを見に行っているという感じは何となくわかるのですが、頭がごちゃごちゃになってしまい難しいです。 ただ、メモリ領域をその方がどのように使おうとしたのかでもわかれば何となくそのプログラムを読み解くことができるようになる感じがするのですが、ポインタなどからそれをグラフィック表示してくれるようなフリーソフトなどはないでしょうか? どなたかご存じの方いらっしゃいましたらご教授お願いいたします。

  • ポインタのポインタとrealloc

    先程関数による動的確保について質問させていただき、ヒントを与えていただいたのですが、そこからまた疑問が生じました。 テストプログラムを作ったのですが、何やら動作がおかしいみたいです おかしい部分を抜き出したソースは次のとおりです int main() {  int **p;  int i;  p = (int **)malloc(sizeof(int *));  *p = (int *)malloc(sizeof(int));  p[0]=0;  for(i=1;i<10;i++){   *p = (int *)realloc(*p,sizeof(int)*(i+1));   *p[i] = i;  }  free(*p);  return 0; } 関数部として作りたい部分をメインにして抜き出しました。 このようにするとreallocがメモリ領域を拡張してくれなく(?)、*p[i] = i;の部分でエラー終了します。 ポインタのポインタではなく、ポインタを用いた時は正常に動作するのですが、何がまずいのでしょうか。 もし宜しければお願いいたします。 ちなみに私は学部4年生で、プログラムの使用は大学の研究用レベルです。

  • ポインタを引数で使用する場合

    初心者です。 ローカル関数でポインタを引数で使用する場合の定義で int A (int *x,int *y) とする場合の*はポインタの宣言としての*なのでしょうか? これまでの例題ではメイン関数のなかでポインタを宣言しアドレスを代入し・・・という使い方だったのですがローカル関数で引数を使用するさいはメイン関数内ではポインタの宣言はないので関数の定義と同時にint *x とint *yを宣言するという事なのでしょうか? それ以降の*は間接参照演算子ですね。

紙詰まり解消シートとは?
このQ&Aのポイント
  • 紙詰まり解消シートについてまとめました。
  • 紙詰まり解消シートの詳細について解説します。
  • 紙詰まり解消シートの使い方や注意点について説明します。
回答を見る

専門家に質問してみよう