C++初心者です。周囲に質問できる人がいないため、こちらで相談させてください。
大きなサイズのArrayの作成に関して、疑問があります。
例えば、以下のコードは問題なく動作しています。
ところが以下のようにc1をクラスメンバとして宣言しコンパイルすると、EXC_BAD_ACCESSとなってしまいます。
ここで、配列のサイズを小さく(たとえば c[1000000][3])するとEXC_BAD_ACCESSが出なくなります。
この原因は一体なぜでしょうか。また、今回のようにクラスメンバに大きなサイズの配列を用いたい場合はどのようにするのが良いのでしょうか。
(開発環境にはMac(Xcode)を使用しています。)
どうぞよろしくお願いいたします。
大きなサイズの配列とEXC_BAD_ACCESSについて
Re: 大きなサイズの配列とEXC_BAD_ACCESSについて
「大きな配列を静的でないローカル変数として確保した結果、アクセス違反」というパターンなので、おそらくスタックオーバーフローでしょう。cotora さんが書きました:この原因は一体なぜでしょうか。
Compiler Explorerのx86-64 gcc 4.8.2、コンパイルオプションなしで変換したところ、
最初のコードは 2番目のコードは
Cls::Cls():
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
popq %rbp
ret
Cls::~Cls():
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
subq $12000000, %rsp
leaq -12000000(%rbp), %rax
movq %rax, %rdi
call Cls::Cls()
leaq -12000000(%rbp), %rax
movq %rax, %rdi
call Cls::~Cls()
movl $0, %eax
leave
ret
最初のコードではスタックポインタを減算しただけで指された(おそらく範囲外の)領域を使用していないのでアクセス違反は発生せず、
2番目のコードではスタックポインタを減算し、指された領域をコンストラクタやデストラクタの呼び出しで使用しているのでアクセス違反が発生したと考えられるでしょう。
インスタンスを動的確保するか、cotora さんが書きました:また、今回のようにクラスメンバに大きなサイズの配列を用いたい場合はどのようにするのが良いのでしょうか。
class Cls{
private:
char c[1000000][12];
public:
Cls(){};
~Cls(){};
};
int main(){
Cls *d = new Cls;
delete d;
}
#include <cstring>
class Cls{
private:
char (*c)[12];
public:
Cls(){
c = new char[1000000][12];
};
Cls(const Cls& cls){
c = new char[1000000][12];
memcpy(c, cls.c, sizeof(char[1000000][12]));
}
Cls& operator=(const Cls& cls){
memcpy(c, cls.c, sizeof(char[1000000][12]));
return *this;
}
~Cls(){
delete[] c;
};
};
int main(){
Cls d;
}
また、配列を使用することにこだわらないのであれば、std::vectorに置き換えるという方法もいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 大きなサイズの配列とEXC_BAD_ACCESSについて
みけCATさん、
ありがとうございます。
とてもわかりやすくて、助かりました!
(確かにstatic char c[1000000][12]にするとEXC_BAD_ACCESSがでなくなりました。)
インスタンスの動的確保も、目から鱗でした。
ありがとうございます。
とてもわかりやすくて、助かりました!
(確かにstatic char c[1000000][12]にするとEXC_BAD_ACCESSがでなくなりました。)
インスタンスの動的確保も、目から鱗でした。