質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Q&A

解決済

3回答

2744閲覧

動的配列でのコアダンプ (環境による動作の違い)

kami2718

総合スコア6

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

0グッド

0クリップ

投稿2020/06/28 17:27

編集2020/06/28 18:40

前提・実現したいこと

C言語で動的配列をmallocを用いて作成し、全要素を合計するプログラムを作ろうとしました。

発生している問題・エラーメッセージ

はじめは、Ubuntuで実行してみましたが、コアダンプが発生しました。
原因がわからなかったので、windowsでもやってみたら問題なく動作しました。
ついでに、CentOSでもやってみたらUbuntuと同じようにコアダンプが発生しました。

デバッグで各行の間にprintf関数を入れてみました。どうやら

array[0][0] = 1;

の行以降は動いていないようです。

しかもWindowsでは動いてくれて、Linuxでだめだなんて。。
コンパイラの仕様による違いがあることはわかりますが、こんな基本的なところで違いがあるのか疑問に思いました。
長くなりましたが結論、Linux環境でも問題なく動くにはどこをコード修正したらいいか教えていただけたら幸いです。

[Ubuntuの実行結果]

test1 test2 test3 test4 Segmentation fault (コアダンプ)

[Windowsの実行結果]

test1 test2 test3 test4 test5 test6 test7 test8 A[0][0] = 1 A[0][1] = 2 A[1][0] = 3 A[1][1] = 4 ans=10 test9 forLoopTest[0][0] array[0][0] = 1 forLoopTest[0][1] array[0][1] = 2 forLoopTest[1][0] array[1][0] = 3 forLoopTest[1][1] array[1][1] = 4

[CentOSでの実行結果]

[Ubuntuの実行結果]とまったく同じ

該当のソースコード

C言語

1#include <stdio.h> 2#include <stdlib.h> 3 4void sumArray(int **A,int size); 5 6int main(void) { 7 int length = 2; 8 9 printf("test1\n"); 10 int **array; 11 printf("test2\n"); 12 array = (int**)malloc(sizeof(int) * length * length); 13 printf("test3\n"); 14 if(array == NULL) { 15 printf("error: malloc\n"); 16 } 17 18 printf("test4\n"); 19 array[0][0] = 1; 20 printf("test5\n"); 21 array[0][1] = 2; 22 printf("test6\n"); 23 array[1][0] = 3; 24 printf("test7\n"); 25 array[1][1] = 4; 26 27 printf("test8\n"); 28 sumArray(array,length); 29 printf("test9\n"); 30 31 int i,j; 32 for(i=0;i<length;i++) { 33 for(j=0;j<length;j++) { 34 printf("forLoopTest[%d][%d]\n",i,j); 35 printf("array[%d][%d] = %d\n",i,j,array[i][j]); 36 } 37 } 38 39 free(array); 40 return 0; 41} 42 43void sumArray(int **A,int size) { 44 int ans = 0; 45 int i,j; 46 for(i=0;i<size;i++) { 47 for(j=0;j<size;j++) { 48 printf("A[%d][%d] = %d\n",i,j,A[i][j]); 49 ans += A[i][j]; 50 } 51 } 52 printf("ans=%d\n",ans); 53 54 return; 55}

試したこと

調べてみて、動的構造体の場合は、Javaでいうインスタンス化のようなものが必要で多くの人がコアダンプで苦しめられているようでしたが、今回は配列だからインスタンス化しなくてもいいよね。と考えたりしました。
ただの配列への代入で、なぜコアダンプが起こるのかわかりません。

補足情報(FW/ツールのバージョンなど)

Ubuntu:

$ cc --version cc (Ubuntu 9.3.0-10ubuntu2) 9.3.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Windows:

>gcc --version gcc (MinGW.org GCC Build-20200227-1) 9.2.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

CentOS:

$ cc --version cc (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5) Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2020/06/28 18:05 編集

int **array;で、array[0][0] = 1;て、おかしくないですか?
kami2718

2020/06/28 18:30

すみません。 具体的にどのようにおかしいのか、教えていただけないでしょうか。
guest

回答3

0

ベストアンサー

こういう感じですかね。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int main(void) 5{ 6 int length = 2; 7 int **array, *base_array; 8 9 array = malloc(sizeof(int*) * length); 10 base_array = malloc(sizeof(int) * length * length); 11 12 if (array == NULL || base_array == NULL) { 13 printf("error:malloc"); 14 return 0; 15 } 16 17 for (int i = 0; i < length; i++) { 18 array[i] = base_array + i * length; 19 } 20 21 array[0][0] = 1; 22 array[0][1] = 2; 23 array[1][0] = 3; 24 array[1][1] = 4; 25 26 for (int i = 0; i < length; i++) { 27 for (int j = 0; j < length; j++) { 28 printf("array[%d][%d] = %d\n", i, j, array[i][j]); 29 } 30 } 31 32 free(base_array); 33 free(array); 34 return 0; 35} 36

投稿2020/06/28 19:01

編集2020/06/28 19:11
Penpen7

総合スコア698

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kami2718

2020/06/28 19:24

ありがとうございました!! 無事解決しました。 二次元配列の場合は2重でメモリを確保しなければならないのですね。
guest

0

C99 の規格では可変長配列が使用できるので、
ソースを次のように変更すれば、gcc で動くはずです。

diff

1-void sumArray(int **A,int size); 2+void sumArray(int size, int (*A)[size]); 3 4- int **array; 5+ int (*array)[length]; 6 7- array = (int**)malloc(sizeof(int) * length * length); 8+ array = (int(*)[2])malloc(sizeof(int) * length * length); 9 10- sumArray(array,length); 11+ sumArray(length, array); 12 13-void sumArray(int **A,int size) { 14+void sumArray(int size, int (*A)[size]) {

Visual C++ は C99 には対応していないのでダメです。

追記

  • array = (int(*)[2])malloc(sizeof(int) * length * length);

は次のように変更してください。

  • array = (int(*)[length])malloc(sizeof(int) * length * length);

投稿2020/06/29 00:14

編集2020/06/29 01:17
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ありがとうございました!!
無事解決しました。
二次元配列の場合は2重でメモリを確保しなければならないのですね。

投稿2020/06/28 19:23

kami2718

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2020/06/28 19:29

実際にどのようなコードで解決されたのか。(Penpen7さんの回答を参考にされたのではないのですか?)
kami2718

2020/06/28 19:34

失礼しました。 初めての利用でしたので、間違えてしまいました。
dodox86

2020/06/28 19:44

ああ、「ありがとうございました」はPenpen7さんにかかっていたのですね。(コメント含め、複数回答があったので分かりませんでした) そのような場合はやはりPenpen7さんにベストアンサー(BA)を振り替えるのが良いと思います。(BAの変更はできるはず。。。ちょっと私では分かりませんが)他回答を参考にしつつ、直接的な解決策を自分で導きだしたときは自己回答~解決も有り、だと思います。
kami2718

2020/06/28 19:53

ご指摘ありがとうございます。 ベストアンサーは変更できました。
thkana

2020/06/28 23:19

(あまり同意見の人を見たことがないのですが)今回使っているのは二次元のデータ構造ではあっても(C言語の規格でいう)二次元配列ではありません。 Cでは、多次元の配列というのは低次元の配列の配列です。で、今回使っているのは配列へのポインタの配列によって低次元の配列をまとめ上げたもの。 違いを意識して、今回使ったようなデータ構造を、(文法通りの意味の)二次元配列を要求している関数の引数に渡したりするようなことはくれぐれもなさいませんよう気をつけて下さい。 (でも、Javaでは今回のようなものを多次元配列と呼ぶから話はややこしい...)
dodox86

2020/06/29 00:26

>thkanaさん > 今回使っているのは二次元のデータ構造ではあっても(C言語の規格でいう)二次元配列ではありません。 実は私もこの点、少し気になっていたのですが、、array[row][column]のコード表記でアクセスしたいのが要望なのかと思って特に指摘はしませんでした。ちょっと発展して、N次元配列のメモリ上での要素の連続性に期待してポインタでアクセスするようなコードになったら危険ですね。C言語(C++か?)におけるN次元配列でのメモリの連続性についてはteratailで以前に質問回答にありました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問