2017-02-06 11 views
-3

私のクラスでoperator=がオーバーロードされていて、文字列に数字が含まれているかどうかを判断する必要があります。残念ながら、私は2つの理由のために、主にC配列(char*)を使用する必要があります。私の関数にcharを渡そうとしているときにSIGSEGVを取得し、それを修正する方法はなぜですか?

  • トレーニング
  • はstdを使用::文字列はコードの100の+の行を変更するために私が必要となります。

    char*の配列の値を関数に渡そうとすると、本当に良いSEGFAULTが得られます。なぜなら、残念なことに、なぜ私はその理由がわかりません。おそらく、私は正しく私のポインタを使用していないでしょう。

私は何時間も探していましたが、この問題の解決策を見つけることができませんでした。とにかく、ここにコードです。この問題に関するさらに詳しい情報が必要な場合は、私にコメントでお知らせください。

#include <limits.h> 
    #include <iostream> 
    #include <string.h> 
    #include <exception> 

    struct notdig : public std::exception { 
    virtual const char* what() const throw() override{ 
     return "int_huge: isdig(*(o + i)) returned false. \nYour declaration of an int_huge integer should contain decimal digits."; 
    } 
}; 
class int_huge { 
    private: 
     char* buffera;     
     char* bufferb; 
     int numDig(unsigned long long int number){ //Gets the number of digits 
      int i = 0; 
      while(number){ 
       number /= 10; 
       i++; 
      } 
      return i; 
     } 
     inline bool isdig(char character) { //Checks whether character is digit or not 
      return ('0' <= character && character <= '9'); 
     } 
    public: 
     int_huge(){ 
      this->buffera = "0"; 
      this->bufferb = "0"; 
     } 
     void operator=(char* operand){ 
      for (int i = 0; i < strlen(operand); i++){ 
       if (!isdig(operand[i])){ 
        throw notdig(); 
       } 
      } 
      if (strlen(operand) >= numDig(ULLONG_MAX)){ 
       if (strlen(operand) - numDig(ULLONG_MAX)){ //Equivalent with if (strlen(operand) != numDig(ULLONG_MAX) 
        int i = 0; 
        while (i < strlen(operand)-numDig(ULLONG_MAX)){ 
         this->buffera[i] = operand[i]; 
         i++; 
        } 
        this->bufferb = operand + i; 
       } else { 
        this->buffera[0] = operand[0]; 
        this->bufferb = operand + 1; 
       } 
      } else { 
       this->buffera = "0"; 
       this->bufferb = operand; 
      } 
     } 
    }; 




    int main() { 
     int_huge object; 
     try { 
      object = "90"; 
     } catch (std::exception &e) { 
      std::cout << e.what(); 
     } 
    } 

逆アセンブラ結果:

0x4019b4 push %ebp 
0x4019b5 mov %esp,%ebp 
0x4019b7 push %ebx 
0x4019b8 sub $0x24,%esp 
0x4019bb mov 0xc(%ebp),%eax 
0x4019be mov %eax,(%esp) 
0x4019c1 call 0x401350 <strlen> 
0x4019c6 mov %eax,%ebx 
0x4019c8 movl $0xffffffff,0x4(%esp) 
0x4019d0 movl $0xffffffff,0x8(%esp) 
0x4019d8 mov 0x8(%ebp),%eax 
0x4019db mov %eax,(%esp) 
0x4019de call 0x40195c <int_huge::numDig(unsigned long long)> 
0x4019e3 cmp %eax,%ebx 
0x4019e5 setae %al 
0x4019e8 test %al,%al 
0x4019ea je  0x401aa8 <int_huge::int_huge(char*)+244> 
0x4019f0 mov 0xc(%ebp),%eax 
0x4019f3 mov %eax,(%esp) 
0x4019f6 call 0x401350 <strlen> 
0x4019fb mov %eax,%ebx 
0x4019fd movl $0xffffffff,0x4(%esp) 
0x401a05 movl $0xffffffff,0x8(%esp) 
0x401a0d mov 0x8(%ebp),%eax 
0x401a10 mov %eax,(%esp) 
0x401a13 call 0x40195c <int_huge::numDig(unsigned long long)> 
0x401a18 cmp %eax,%ebx 
0x401a1a setne %al 
0x401a1d test %al,%al 
0x401a1f je  0x401a8d <int_huge::int_huge(char*)+217> 
0x401a21 movl $0x0,-0xc(%ebp) 
0x401a28 mov 0xc(%ebp),%eax 
0x401a2b mov %eax,(%esp) 
0x401a2e call 0x401350 <strlen> 
0x401a33 mov %eax,%ebx 
0x401a35 movl $0xffffffff,0x4(%esp) 
0x401a3d movl $0xffffffff,0x8(%esp) 
0x401a45 mov 0x8(%ebp),%eax 
0x401a48 mov %eax,(%esp) 
0x401a4b call 0x40195c <int_huge::numDig(unsigned long long)> 
0x401a50 sub %eax,%ebx 
0x401a52 mov %ebx,%edx 
0x401a54 mov -0xc(%ebp),%eax 
0x401a57 cmp %eax,%edx 
0x401a59 seta %al 
0x401a5c test %al,%al 
0x401a5e je  0x401a7d <int_huge::int_huge(char*)+201> 
0x401a60 mov 0x8(%ebp),%eax 
0x401a63 mov (%eax),%edx 
0x401a65 mov -0xc(%ebp),%eax 
0x401a68 add %eax,%edx 
0x401a6a mov -0xc(%ebp),%ecx 
0x401a6d mov 0xc(%ebp),%eax 
0x401a70 add %ecx,%eax 
0x401a72 movzbl (%eax),%eax 
0x401a75 mov %al,(%edx)  ;This is where the compiler stops. Probably due to SIGSEGV. 
0x401a77 addl $0x1,-0xc(%ebp) 
0x401a7b jmp 0x401a28 <int_huge::int_huge(char*)+116> 
0x401a7d mov -0xc(%ebp),%edx 
0x401a80 mov 0xc(%ebp),%eax 
0x401a83 add %eax,%edx 
0x401a85 mov 0x8(%ebp),%eax 
0x401a88 mov %edx,0x4(%eax) 
0x401a8b jmp 0x401aba <int_huge::int_huge(char*)+262> 
0x401a8d mov 0x8(%ebp),%eax 
0x401a90 mov (%eax),%eax 
0x401a92 mov 0xc(%ebp),%edx 
0x401a95 movzbl (%edx),%edx 
0x401a98 mov %dl,(%eax) 
0x401a9a mov 0xc(%ebp),%eax 
0x401a9d lea 0x1(%eax),%edx 
0x401aa0 mov 0x8(%ebp),%eax 
0x401aa3 mov %edx,0x4(%eax) 
0x401aa6 jmp 0x401aba <int_huge::int_huge(char*)+262> 
0x401aa8 mov 0x8(%ebp),%eax 
0x401aab movl $0x4030d2,(%eax) 
0x401ab1 mov 0x8(%ebp),%eax 
0x401ab4 mov 0xc(%ebp),%edx 
0x401ab7 mov %edx,0x4(%eax) 
0x401aba nop 
0x401abb add $0x24,%esp 
0x401abe pop %ebx 
0x401abf pop %ebp 
0x401ac0 ret 
+0

割り当て演算子を呼び出すコードを表示できますか? – NathanOliver

+0

1)変数の値を観察しながら、デバッガでコードをステップ実行しようとしましたか? 2)[mcve]を提供してください(**あなたのコードをすべて提供する必要はありません**最小限のものを作成するだけですが、完全な例です)。 –

+5

大きな番組の一部ではなく[mcve]を投稿します(大きな番組は、番組全体を管理する番組です)。 – PaulMcKenzie

答えて

3

書き込み可能な記憶装置であってもなくてもよい

o = "90"; 

string literals、で

MyClass(){ 
    this->a = "0"; 
    this->b = "0"; 
} 

Inとmainで、割り当てられています非定数ポインタcharに。コンパイラがC++ 11以上の標準をサポートしている場合、コンパイラはこれを警告したり、コンパイルを完全に拒否したりするはずです。これは、最大吹く

はここoperator=である:ここ

this->a[i] = o[i]; 

と:

this->a[0] = o[0]; 

プログラムを書き込むことができないストレージを書き込もうとして。

ソリューション:

使用std::string。それがテーブルの外にあり、そのように思える場合は、文字列リテラルを使用しないでください。書き込み可能なメモリにバッファを割り当て、newとし、リテラルをバッファにコピーしてバッファを割り当てます。また、バッファーは固定サイズであることを覚えておいてください。大きな文字列をバッファに配置しようとすると、惨事が発生します。

これはメモリ管理の頭痛とホラーショーa potential Rule of Threeになりますので注意してください。

+0

ありがとう、あなたの助け:)私のために何かを指摘できますか?書き込めない記憶域を書き込むと予期しない動作が起こる可能性がありますか? –

+0

@DemetriosCollier Cプログラムでは、[未定義の動作](http://en.cppreference.com/w/cpp/language/ub)が必ず発生します。 C++は型チェックのためにさらに厳しいので、同じことを期待しています。あなたに章と詩を挙げることはできません。 – user4581301

+0

Ah。さて、私はそれを得る。どうもありがとう。 –

関連する問題