为什么我在尝试将字符传递给我的函数以及如何修复它时会获得 SIGSEGV

Why do I get SIGSEGV when trying to pass a char to my function and how to fix it?

本文关键字:何修复 SIGSEGV 函数 我的 字符 为什么      更新时间:2023-10-16

我在类中重载了operator=,我需要确定我的字符串是否包含数字。 不幸的是,我需要主要使用 C 数组 ( char* (,原因有两个:

  • 训练
  • 使用 std::string 将需要我更改 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

in

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

并在main

o = "90";

字符串文本(可能不在可写存储中(分配给指向 char 的非常量指针。编译器应该警告您这一点,或者如果编译器支持 C++11 或更高版本的标准,则直接拒绝编译。

这爆炸的地方在这里operator=

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

在这里:

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

当程序尝试写入无法写入的存储时。

溶液:

使用 std::string .如果这不在桌面上,并且听起来确实如此,请不要使用字符串文字。使用 new 在可写内存中分配缓冲区,将文本复制到缓冲区中,然后分配缓冲区。还要记住,缓冲区的大小是固定的。尝试在缓冲区中放置较大的字符串将导致灾难。

这将是一个令人头疼的记忆管理问题,也是一个潜在的三法则恐怖节目,所以要小心。