• ベストアンサー

C言語 動的なメモリの確保 実行できない

malloc関数を使いメモリを確保しそこへ"ABCD"と記憶させ、ポインタ*Cを使い確保したメモリの内容を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int i;   char *C;   C = (char *) malloc (sizeof(char) * 5);   C = "ABCD";   for(i = 0; i < 5; i++){     if(C[i] != NULL){       printf("%s", C[i]);    ←※エラー※     }   }   free(C);   return 0; } ********************************************* 正常にコンパイルできますが実行エラーになります。VCを使いF10のデバッグテストで※のところエラーになります。なぜなのでしょうか?

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

C[i] は、char で、%s の要求するchar * ではないから。 あと、 C = (char *) malloc (sizeof(char) * 5); で確保したメモリに文字列を設定するには、 strcpy (または、strncpy,stpcpy)を使います。 C = "ABCD"; したら free(C) は、malloc で確保したのとは違う領域を開放しようとしてエラーになります。(アドレスの代入によって、確保した領域はアクセスできなくなります) printf で文字列を表示するなら printf("%s", C); で 1文字ずつ表示するなら printf("%c",C[i]); でします。

ikepan
質問者

お礼

ご返答ありがとうございます。 strcpy関数を使えば良いという事だけではなく、内部的な動きまで丁寧に教えていただきとても理解できました。おかげで実行できました。

その他の回答 (1)

  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

> C = (char *) malloc (sizeof(char) * 5); ここでポインタ変数Cに、mallocで確保した領域へのポインタが代入されていますが、 > C = "ABCD"; ここで文字列リテラル"ABCD"を指すものに上書きされています。 結果として、mallocで確保した領域へのポインタが分からなくなってしまったので、 後でfreeで開放することができなくなります。(メモリリーク) > C[i] != NULL C[0]やC[1]は、ここでは'A'や'B'などの文字なので ポインタであるNULLと比較するのはおかしいです。 文字である'\0'と比較したほうが意味が通ります。  C[i] != '\0' > printf("%s", C[i]); 先に書いたように、C[i]は文字なので、 文字列(実際は文字列の先頭文字へのポインタ)を要求する%sと合わせて使うとおかしな結果になります。 (エラーの直接の原因はこれでしょう。)  printf("%c", C[i]); もしくはループさせずに  printf("%s", C); とするべきです。 > free(C); 先に書いたように、Cはこの時点で文字列リテラル"ABCD"を指しているので、 freeすると問題が発生するかもしれません。

ikepan
質問者

お礼

ご返答ありがとうございます。 No,1様の回答にはなかった他の箇所の指摘と動きの説明までしていただき、とても理解できました。おかげで実行できるようになりました。

関連するQ&A

  • C言語 動的なメモリの確保 コンパイル時エラーも警告もないのに実行できない

    配列A[3]を{2, 4, 6}と初期化させ、malloc関数を使いメモリを確保しそこへ先程の配列Aの要素を記憶させ、ポインタ*Nを使い確保したメモリの要素を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int A[3] = {2, 4, 6};   int i;   int *N;   N = (int *) malloc (3);   for(i = 0; i < 3; i++){     N[i]= A[i];   }   for(i = 0; i < 3; i++){     printf("%d", N[i]);   }   free(N);   return 0; } ********************************************* VCを使いF10のデバッグテストでは正常に動くのですが、コマンドラインからではエラー報告画面がでます。なぜなのでしょうか?

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • メモリ確保の謎。

    C言語のメモリの確保の所でふと疑問に思ったのですが、 malloc,calloc,realloc,memset,memcpyなどの関数を使うときって #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <malloc.h> とか書かないといけないと本にはありますが、#include <stdio.h>だけで なんのエラーにもならずに実行できてしまうのはなぜでしょうか? 実際のプログラムにはmallocとreallocしか使ってないのですが、#include <stdio.h>でできてしまいます。 でも教科書には他にも書かなきゃいけないとかいてありますが、なぜ書かなくても実行できてしまうのでしょうか?

  • ポインタで、実装メモリの先頭から100バイト分参照してみたい

    いつもお世話になります。 Cの質問です。 ポインタの勉強中なのですが、ポインタを用いて、実装メモリの先頭から100バイト分を参照してみたい、と思いました。 先輩が言うには「メモリの先頭領域にはメモリのメーカーとか、文字コードが順番に入ってるよ」とのことなのですが、どうにもプログラムが作れません。 mallocでは、どうやら「コンパイル時にメモリ領域を確保する」らしく、指定したメモリ位置(つまりアドレス0)からxxバイト分確保することはできないようです。 私が試しに書いてみたソースは以下になります。 #include<stdio.h> #include<stdlib.h> int main(void){ int i; char *p; p = (char*)malloc(sizeof(char) * 100); for (i=0;i<100;i++){ printf("%c",*p); p++; } return (0); } アドバイスでもかまいませんので、ご指導いただけたらと思います。 よろしくお願いいたします。

  • C言語のポインタ

    あまり意識せずにポインタを使っているせいか,次のプログラムではまってしまいました. #include<stdio.h> #include<stdlib.h> int main(void) {  int *p, q;  p = (int *)malloc(sizeof(int));  q = (int *)malloc(sizeof(int));  *p = 2;  printf("%d\n", *p);  return 0; } コンパイルエラーで実行ファイルが出力されません. このプログラムで変数qはなぜポインタじゃないのでしょうか? 次にtypedefでptr_intという型を定義したプログラムは, 上のようなエラーが出力されず,期待とおりの結果になりました. #include<stdio.h> #include<stdlib.h> typedef int* ptr_int; int main(void) {  ptr_int p, q;  p = (int *)malloc(sizeof(int));  q = (int *)malloc(sizeof(int));  *p = 2;  *q = 3;  printf("%d\n", *p);  printf("%d\n", *q); return 0; } typedefすることでなぜエラーを回避することができるのでしょうか? よろしくおねがいします.

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

    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; }

  • メモリ動的確保について

    こんにちはです。 メモリの動的確保なのですが、 typedef struct DATA{ char name[256]; char pass[256]; int money; }BANK; void insert(BANK *p,int max); int main(){ int i; size_t st; BANK *person; person = (struct DATA *)malloc(sizeof(struct DATA)); //person = (struct DATA *)malloc(5); if(person == NULL){ printf("確保失敗\n"); exit(-1); } //memset(person,'\0',sizeof(struct DATA)); と、言う風に、記載ソースは途中ですがメモリをとりました。 mallocの後ろの部分ですが、sizeof(struct DATA)と5ではどうちがうのでしょう??2通りともコンパイルエラーはないです。 5は動的に最大5までとるって事はわかるのですが、struct DATAの方はいくつとるのです??いくつもで入力次第です? そして、動的したのにたいしてmemsetしたら実行エラー(コンパイルは通りました)おきました。動的にたいしてmemはダメなのでしょうか? アドバイスいただけたらありがたいです。宜しくお願いいたします。

  • C言語の領域確保について

    C言語を始めたばかりのものです。 配列を計算させようと下のようなプログラムを作り、一応動作はするのですが、配列の領域確保がいまいちわかりません。配列はcsvから値をとっています。確保する領域は、代入する値の数でいいので、buff[8×64]、とかarv[4×32]でいいと思い、それより少し大きな値くらいで実行すると失敗してしまいます。  自分の理解の仕方が間違っているとは思っているのですが、(char *)malloc(M*N*sizeof(char))でやっても失敗しました。どうすればよいかお教え願います。ちなみに、csvの値は0.000852354710804709のように桁が半端ないです。  またfgetsのライン数の値も正しくするにはどうすればよいのでしょうか。できたらmallocを使えたらよいと思っています。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define N 8 //8行 #define M 64 //64列 int main() { char *fname = "test.csv";//8行64列 char *ffname = "tk.csv";//4行32列 FILE *IN1, *IN2, *OUT1, *OUT2; char buff[100000];//←問題の部分 char *pbuff; char arv[400];//←問題の部分 char *parv; double a[N][M+30], b[N][M], c[N][M], w[4][32]; int i, j, x; double m, n; int count=0; if((IN1 = fopen(fname, "r")) == NULL){ printf("can't open the %s", fname); return 0; } if((IN2 = fopen(ffname, "r")) == NULL){ printf("can't open the %s", ffname); return 0; } i=j=0;//配列の取得 while(fgets(buff, 100000, IN1) != NULL){ pbuff = buff; while((pbuff = strtok(pbuff, ",\n")) != NULL){ a[i][j++] = strtod(pbuff, NULL); pbuff = NULL; } i++; j=0; } i=j=0;//配列の取得 while(fgets(arv, 400, IN2) != NULL){ parv = arv; while((parv = strtok(parv, ",\n")) != NULL){ w[i][j++] = strtod(parv, NULL); parv = NULL; } i++; j=0; }             :             :             : このプログラムでも計算はできるのでいいのですが、最終的には500行2048列の計算をしないといけないので、いっそう数字が膨大となるために質問させていただきました。Visual Stdio 2010 c/c++ 使ってます。

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • C++ 最適なメモリ確保

    画像処理をするために実験的にC++でプログラムを書いています。 malloc関数でBMP画像の画素位置を、画像画素分確保するだけのint型配列を作成するにはどうしたらよいでしょうか。 因みに、入力画像の解像度は640x480です。 一番左下の画素を(x,y)=(0,0)として考えています。 ある条件の画素に該当する画素座標を、下のStackX,StackYにx,y成分ごとに格納していくものです。 //////// int *StackX = (int *)malloc(sizeof(int)*100000); int *StackY = (int *)malloc(sizeof(int)*100000); //////// 上のように書くと、途中でクラッシュしてしまいます。 ですが、大目にメモリをとって //////// int *StackX = (int *)malloc(sizeof(int)*10000000); int *StackY = (int *)malloc(sizeof(int)*10000000); //////// で実行すると、最後まで動いてくれます。