cotora さんが書きました:この原因は一体なぜでしょうか。
「大きな配列を静的でないローカル変数として確保した結果、アクセス違反」というパターンなので、おそらくスタックオーバーフローでしょう。
Compiler Explorerのx86-64 gcc 4.8.2、コンパイルオプションなしで変換したところ、
最初のコードは
コード:
main:
pushq %rbp
movq %rsp, %rbp
subq $11999880, %rsp
movl $0, %eax
leave
ret
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;
}
メンバを動的確保する(
the rule of threeに従い、コピーコンストラクタと代入演算子も定義していることに注意)
コード:
#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に置き換えるという方法もいいでしょう。