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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

コンパイルエラー

コンパイルのフェーズで生成されるエラーです。よく無効なシンタックスやタイプが含まれているとき発生します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

205閲覧

Ubuntuやideone.comでは動作しているのにMacOSではエラーが表示される

wotaku

総合スコア13

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

コンパイルエラー

コンパイルのフェーズで生成されるエラーです。よく無効なシンタックスやタイプが含まれているとき発生します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/05/24 22:50

タイトルの通りなのですが、Ubuntuやideone.comでは動作しているC++で記述したプログラムが、MacOS Mojave 10.14.5にコピペして実行するとSegmentation Fault: 11となってしまいます。
Ubuntuのgccのバージョンは8.2.0で、Macはbrew経由でインストールした9.1.0です。(Macを8.3.0にして試しましたが同様のエラーが表示されました。8.2.0はインストールの方法がわからず試せておりません。)

このように、コンパイラはほとんど同じにもかかわらず環境(OS)が異なるだけで、エラーになる場合などはあるのでしょうか。また、その場合の解決方法についてご教示いただけると幸いです。

ちなみにプログラムは構造体とポインタを用いて二分木を構成するというものです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

他の環境では偶然動いているだけです。
gdb等を使って、どこで落ちてるかをまずは確認しましょう。

場合によっては、valgrindやAddressSanitizerが有効である場合もあります。

投稿2019/05/25 00:01

asm

総合スコア15147

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

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

wotaku

2019/05/25 00:54

ありがとうございます。 たった今エラーとなる具体的な原因が判明しました。 Ubuntuやideoneの環境では構造体が所有するポインタ変数がnewで宣言した際にNULLで初期化されるのに対し、Macでは自動的にアドレスが割当てられることで、条件分岐がおかしくなりエラーが発生していました。 Mac環境で、構造体の定義文にあらかじめNULLで初期化するよう追記したところ、うまく動作しました。 このようなポインタ変数などの宣言時の初期化の状態が異なるというのは、コンパイラの仕業なのでしょうか。それともOSに依存しているのでしょうか。 可能であれば、MacにおいてもUbuntuと同様の(初期化)状態を再現したいのですが…。
asm

2019/05/25 01:39

構造体をnewで確保した際の構造体内のポインタが不定値だった。 ということでしょうか? C++言語仕様的には不定値で正しく、偶然Ubuntu環境において0だった。それだけです。 初期化に関する挙動をデフォルトで再現させるのは困難なように思います。 #include <cstdlib> void* operator new(std::size_t t){ return std::calloc(1,t); } void operator delete(void* p) noexcept{ std::free(p); } という手段もありますが。 きちんと初期化するのが最善でしょう。
wotaku

2019/05/25 02:25

ありがとうございます。 本来は不定値で初期化されるのが正しく、Ubuntuの環境が偶然もしくは特殊だったのですね。勝手に正反対の認識を持っていました。 エラーの原因の発見の手助けをいただいただけでなく、根本的に誤った理解まで正していただき、心から感謝しています。
thkana

2019/05/25 07:56

「不定」の意味をとりちがえているように思います。不定というのは、いかなる特定の値も期待してはいけない、というだけのことです。値が0であることもあり得ます。 実行してみれば変数は何らかの値になっているのですが、プログラムだけからはその値を事前に決定は出来ない、ということです。Ubuntuであっても、同時に走っているプログラムが違ったり、コンパイラやOSのバージョンが違ったり、その他ちょっとしたことで0でない値が得られるかも知れません。
wotaku

2019/05/31 05:16

ありがとうございます。 返答が遅れてしまい申し訳ありません。 > 不定というのは、いかなる特定の値も期待してはいけない、というだけのことです。値が0であることもあり得ます。 すなわち、不定値=無作為(random)な値ということでしょうか。 事前に決定されておらず、定義時に適当な値が割り振られる…という認識です。
thkana

2019/05/31 22:18

> 事前に決定されておらず そうですね。そこを押さえておけば実用上問題はないのですが、 > 定義時に適当な値が割り振られる ここはちょっと違います。ローカル変数を定義したときに行われるのは「メモリのこの位置はこの変数で使う」という領域の確保だけ。内容は、特に初期化の指示がなければ直前に他の何かで使われた状態のまま。「他の何か」は、寿命の尽きた変数かも知れませんし、スタックに積まれた関数呼び出しのリターンアドレス(だったもの)かも、それらの一部や破片のつなぎ合わせかも知れません。「定義時に適当な値が割り振られる」わけではなく、「定義時にたまたまそこにあった値」なのです。 そういう事情なので、特定のシステムであれば特定の値が予期出来る(今回Ubuntuでは毎回NULLが得られた、みたいな)こともあるかもしれませんが、C言語の範囲で管理しているものではないので、言語の規定としては「不定」としかいいようがないのです。 (で、過去の変数の値が読み取れる可能性があるのでセキュリティホールになりうるとかいう話も)
wotaku

2019/06/01 08:13

返信ありがとうございます。 > ローカル変数を定義したときに行われるのは「メモリのこの位置はこの変数で使う」という領域の確保だけ。内容は、特に初期化の指示がなければ直前に他の何かで使われた状態のまま。 なるほど。基本的に初期化という処理を行わない限り、メモリ上では過去に使用された値やその残骸が残されたままで、確保した領域次第でどのような値も取り得ると…。故に不定(定められていない)値ということなのですね。意外な発見をさせていただきました。 やはりポインタなどを扱う場面では必然的にメモリという概念についてある程度深く理解しておかなければなりませんね。自分に不足した知識を得るところから始める必要があると強く実感しました。 この度は本当にありがとうございました!
thkana

2019/06/01 16:46

はい、そういうことです。 なお、グローバル変数は原則(特に指定しなければ)0に初期化することになっています。プログラムの起動時にたかだか一回行われるだけなので。 一方、ローカル変数は、関数呼び出し毎に確保されるので、これを一々初期化してたらそのコストが馬鹿にならない...ということだったのでしょう。Cが開発された1970年代の遅いコンピュータでは特に。(もちろん、今でも呼び出し頻度が高くなればパフォーマンスに影響があります)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問