分段错误(核心转储)未显示在 gdb 中



我尝试将一些C++代码转换为程序集。该程序使用迭代回溯算法来查找数组的排列,并选择满足某些条件的第一个排列。

C++代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int m,c;
int x=0;
bool verify(vector<int> v, int m){
for(int i = 1;i<=c;i++){
int found=0;
int cnt=0;
for(int j=0;j<v.size();j++){
if(found==1){
cnt++;
if(v[j]==i){
if(cnt<=m)
return false;
cnt=0;
}
}
if(v[j]==i){
found=1;
}
}
}
return true;
}
void permutations(vector<int> s,int m, vector<int> v,vector<int> zeros)
{
int n = s.size();

if (n == 0) {
return;
}

if(n==1){
return;
}
while (1)
{
int j = 0;
for(int i = 0; i < v.size(); i++){
if(v[i]==0){
v[i]=s[j];
j++;
}
}
if(verify(v,m)){
for(int i = 0; i<v.size();i++){
cout<<v[i]<<' ';
}
x=1;
return;
}        
else{
for(int i = 0; i<zeros.size();i++){
v[zeros[i]]=0;
}
}

int i = n - 1;
while (s[i-1] >= s[i])
{
if (--i == 0) {
return;
}
}

j = n - 1;
while (j > i && s[j] <= s[i - 1]) {
j--;
}

swap(s[i - 1], s[j]);

reverse (s.begin() + i, s.end());
}
}

int main()
{
cin>>c>>m;
vector<int> v(3*c);
for(int i = 0;i<3*c;i++)
cin>>v[i];
int j =0;
vector<int> str(3*c);
for(int i = 1;i<=c;i++){
str[j]=i;
j++;
str[j]=i;
j++;
str[j]=i;
j++;
}
for(int i=0;i<3*c;i++){
if(v[i]!=0){
for(int k = 0;k<3*c;k++){
if(str[k]==v[i]){
str.erase(str.begin()+k);
break;
}
}
}

}
vector<int> zeros(0);
j=0;
for(int i=0;i<3*c;i++){
if(v[i]==0){
zeros.push_back(i);
j++;
}
}

permutations(str,m,v,zeros);
if(x==0)cout<<-1;

return 0;
}

当我尝试使用输入5 1 1 0 0 0 0 0 3 0 0 0 0 0 0 4 5运行asm代码时,我会出现Segmentation错误(核心转储(,但当我使用gdb调试代码时,程序成功完成,我甚至不知道从哪里开始查找。

.data
c: .long 0
zeros: .space 400
x: .long 0
sir: .space 400
n: .long 0
m: .long 0
v: .space 400
delim: .asciz " "
formatScanf: .asciz "%400[^n]"
length: .long 0
sirlength: .long 0
j: .long 0
str: .space 400
zero: .long 0
l: .space 4
d: .space 4
check: .long 0
formatPrintf: .asciz "%d "
jnk: .long 0
final: .asciz "n"
formatPrintf2: .asciz "%c"
.text

verify:
pushl %ebx
pushl %esp
pushl %ebp
pushl %esi
pushl %edi
movl $3, %eax
movl %esp, %esi
mul %esi
movl %esi, %eax 
movl $0, %ecx
movl $-1, %ebx

jmp for

for:
add $1, %ecx
cmp %ecx, %esp
jl return_verify_true

movl $0, -24(%esp)
movl $0, -28(%esp)
movl $-1, %ebx
jmp for_for
for_for:
add $1, %ebx
cmp %ebx, %ebp
je for
cmp $1, -24(%esp)
je found
jmp not_found

found:
add $1, -28(%esp)
cmp (%edi, %ebx, 4), %ecx
je adevarat

jmp not_found

not_found:
cmp (%edi, %ebx, 4), %ecx
je add1

jmp for_for

adevarat:
movl -28(%esp), %edx
cmp %edx, 12(%esp)
jl return_verify_false

movl $0, -24(%esp)

jmp for_for
return_verify_true:
popl jnk
popl jnk

popl %edi
popl %esp
popl %ebp
popl %esi
popl %edi

add $20,  %esp
movl $1, %eax
jmp final_permutations

return_verify_false:
popl jnk
popl jnk

popl %edi
popl %esp
popl %ebp
popl %esi
popl %edi

movl $0, %eax

jmp while1
add1:
add $1, -24(%esp)
jmp for_for

permutations:

pushl %ebx
pushl %esp
pushl %ebp
pushl %esi
pushl %edi

lea v, %edi
lea str, %esi
lea zeros, %edx

sub $20, %esp

cmp $0, 4(%esp)
je return

cmp $1, 4(%esp)
je numaru1

jmp while1

numaru1:
movl %esi, %ecx
movl %ecx, (%edi, %edx,4)

call verify
while1:
movl $0, %ebx
movl $-1, %ecx  

for_in_while:
add $1, %ecx
cmp %ecx, %ebp
jl for_in_while_exit

cmp $0, (%edi, %ecx, 4)
je este_zero

jmp for_in_while

este_zero:
movl (%esi, %ebx, 4), %eax
movl %eax, (%edi, %ebx, 4)
add $1, %ebx
jmp for_in_while
for_in_while_exit:

movl $-1, %ebx

call verify
cmp $1, %eax
je crazy
jmp not_crazy   
crazy:
add $1, %ebx
cmp %ebx, %ebp
jge crazy_exit

pushl $formatPrintf
pushl (%edi, %ebx, 4)
call printf
popl %edx
popl %edx

jmp crazy

movl $1, check
ret

not_crazy:
add $1, %ebx
cmp %ebx, 4(%esp)
jge crazy_exit

movl (%edx, %ebx, 4), %eax
movl $0, (%edi, %eax, 4)

jmp not_crazy

crazy_exit:
movl %esp, %eax
sub $1, %eax
movl %eax, %ebx
sub $1, %ebx

while2:

movl (%esi, %ebx, 4), %ecx
cmp %ecx, (%esi, %eax, 4)
jl while2_exit

sub $1, %ebx
sub $1, %eax

cmp $0,%ebx
je return

jmp while2  

while2_exit:

movl %esp, %ecx
sub $1, %ecx
movl %eax, jnk
while3:

cmp %ecx, %eax
jg break
movl (%esi, %ecx, 4), %eax
cmp %eax, (%esi, %ebx, 4)
jl break

sub $1, %ecx

jmp while3

break:
movl jnk, %eax
sub $1, %eax

movl (%esi, %eax, 4), %edx
movl %ecx, (%esi, %eax, 4)
movl %edx, %ecx

add $1, %eax
lea str, %edi
movl 4(%esp), %ebx

reverse:
cmp %eax, 4(%esp)
je while1

movl (%esi, %eax, 4), %edx
movl (%edi, %ebx, 4), %ecx
movl %ecx, (%esi, %eax, 4)
movl %edx, (%edi, %ebx, 4)

jmp reverse

return:
popl jnk
popl jnk

popl %edi
popl %esp
popl %ebp
popl %esi
popl %edi

add $20,  %esp
jmp final_permutations


.global main
main:
pushl $sir
pushl $formatScanf
call scanf
popl %ebx
popl %ebx

pushl $sir
call strlen
popl %ebx
movl %eax, sirlength    
movl %eax, length

pushl $delim
pushl $sir
call strtok
popl %ebx
popl %ebx

sub $48, %eax

movl %eax, n

pushl $delim
pushl $0
call strtok
popl %ebx
popl %ebx

sub $48, %eax

movl %eax, m

movl $0, %ecx
lea v, %edi

et_for:
pushl $delim
pushl $0
call strtok
popl %ebx
popl %ebx

sub $48, %eax

movl %eax, (%edi, %ecx, 4)

add $1, %ecx

cmp %ecx, length
jg et_for

movl $1, %eax
lea str, %edi
movl $0, %ecx

et_for2:

movl %eax, (%edi, %ecx, 4)
add $1, %ecx

movl %eax, (%edi, %ecx, 4)
add $1, %ecx

movl %eax, (%edi, %ecx, 4)
add $1, %ecx

add $1, %eax

cmp %eax, n
jg et_for2

movl $0, %ecx
lea v, %edi
movl $0, %esi
movl $0, %eax
movl $0, %ebx
movl $0, j
movl %ebp, x
lea sir, %ebp
movl %esp, d
et_for3:
movl (%edi, %esi, 4), %esp
movl %esp, zero
cmp $0, zero
jne et_for4

jmp et_for3

et_for4:
movl (%edi, %esi, 4), %edx
cmp (%ebp, %ebx, 4), %edx
je erase

cmp %eax, length
jl et_for3
erase:
add $1, j
movl j, %edx
sub $1, j


movl (%ebp, %edx, 4), %esi
movl j, %esi

sub $1, sirlength

add $1, j
movl length, %esi
sub $1, %esi
cmp j, %esi
jg et_for3
movl $0, j
movl $0, %ecx

lea zeros, %esi 

et_for5:
cmp $0, (%edi, %ecx, 4)
je egal

add $1, %ecx

cmp length, %ecx
jl et_for5

jmp dupa_egal
egal:
movl %ecx, (%esi, %ecx, 4)
add $1, %ecx
jmp et_for5
dupa_egal:

movl x, %ebp
movl d, %esp
pushl length
pushl m
pushl sirlength
pushl n
call permutations
final_permutations: 
popl %ebx
popl %ebx
popl %ebx
popl %ebx

cmp $0, check
je finalfinal

et_exit:

pushl $final
pushl $formatPrintf2
call printf
popl %ebx
popl %ebx
mov $1, %eax
mov $0, %ebx
int $0x80

finalfinal:
pushl $-1
pushl $formatPrintf
call printf
popl %ebx
popl %ebx
jmp et_exit

我甚至不知道从哪里开始寻找

GDB能够进行事后调试。

您所要做的就是查看core转储(通过在GDB之外运行程序生成(,如下所示:

gdb /path/to/executable /path/to/core
(gdb) where

Peter Cordes的评论解释了为什么程序可以运行";精细";在GDB下,但在GDB外崩溃,反之亦然。

最新更新