gpt4 book ai didi

c++ - 为什么段错误是由类变量顺序引起的?

转载 作者:行者123 更新时间:2023-11-27 22:50:43 26 4
gpt4 key购买 nike

我创建了以下程序:

class CLexer
{
public:

CLexer( ) {
iCursorPos = 0;
}

void putCharacter(char character)
{
if(character != ' ' && character != '\n') {
m_strToken[iCursorPos] = character;
iCursorPos++;
}
else {
m_strToken[iCursorPos] = '\0';
iCursorPos = 0;
}
}

private:

char m_strToken[1024];
int iCursorPos = 0;

};

int main(int argc, char * argv[]) {
CLexer lex;
lex.putCharacter('m');
return 0;
}

编译器产生的汇编器输出:

    .file   "main.cpp"
.section .text._ZN6CLexerC2Ev,"axG",@progbits,_ZN6CLexerC5Ev,comdat
.align 2
.weak _ZN6CLexerC2Ev
.type _ZN6CLexerC2Ev, @function
_ZN6CLexerC2Ev:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movl $0, 1024(%rax)
movq -8(%rbp), %rax
movl $0, 1024(%rax)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size _ZN6CLexerC2Ev, .-_ZN6CLexerC2Ev
.weak _ZN6CLexerC1Ev
.set _ZN6CLexerC1Ev,_ZN6CLexerC2Ev
.section .text._ZN6CLexer12putCharacterEc,"axG",@progbits,_ZN6CLexer12putCharacterEc,comdat
.align 2
.weak _ZN6CLexer12putCharacterEc
.type _ZN6CLexer12putCharacterEc, @function
_ZN6CLexer12putCharacterEc:
.LFB3:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movl %esi, %eax
movb %al, -12(%rbp)
cmpb $32, -12(%rbp)
je .L3
cmpb $10, -12(%rbp)
je .L3
movq -8(%rbp), %rax
movl 1024(%rax), %eax
movq -8(%rbp), %rdx
cltq
movzbl -12(%rbp), %ecx
movb %cl, (%rdx,%rax)
movq -8(%rbp), %rax
movl 1024(%rax), %eax
leal 1(%rax), %edx
movq -8(%rbp), %rax
movl %edx, 1024(%rax)
jmp .L4
.L3:
movq -8(%rbp), %rax
movl 1024(%rax), %eax
movq -8(%rbp), %rdx
cltq
movb $0, (%rdx,%rax)
movq -8(%rbp), %rax
movl $0, 1024(%rax)
.L4:
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE3:
.size _ZN6CLexer12putCharacterEc, .-_ZN6CLexer12putCharacterEc
.text
.globl main
.type main, @function
main:
.LFB4:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $1056, %rsp
movl %edi, -1044(%rbp)
movq %rsi, -1056(%rbp)
leaq -1040(%rbp), %rax
movq %rax, %rdi
call _ZN6CLexerC1Ev
leaq -1040(%rbp), %rax
movl $109, %esi
movq %rax, %rdi
call _ZN6CLexer12putCharacterEc
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE4:
.size main, .-main
.ident "GCC: (GNU) 6.1.1 20160501"
.section .note.GNU-stack,"",@progbits

并且在执行后,第一次调用以 'm' 字符作为参数的 putCharacter 方法会抛出段错误。附加的 gdb 给出以下输出:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004018e5 in CLexer::putCharacter (this=0x7fffffffe370,
character=109 'm') at src/main.cpp:60
60 m_strToken[iCursorPos] = character;

我已经通过在类声明中将 iCursorPos 变量移动到 m_strToken 上方来解决这个错误,但我认为这不是解决这个问题的正确方法。

我在 ArchLinux x86_64 的最新更新版本上使用 g++ (GCC) 6.1.1 20160501

最佳答案

if(character != ' ' && character != '\n') {
m_strToken[iCursorPos] = character;
iCursorPos++;
}

你不检查 iCursorPos < 1024这里。所以你写过了缓冲区的末尾,进入iCursorPos本身。

下一个访问m_strToken[iCursorPos] = character;可能会写到缓冲区末尾之外,并且您会遇到段错误(幸运的是)。

您的“修复”仍然不正确,因为无论如何您都破坏了对象内存的其他部分。

关于c++ - 为什么段错误是由类变量顺序引起的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37460741/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com