Which functions may give SIGABRT in C++

Can someone tell me which functions may cause SIGABRT in my code? My code is 235 lines long and I have no clue which functions can cause SIGABRT. If someone can tell me which functions are at risk, It’ll be easier for me to debug my code.
Question : ICM2004 Problem - CodeChef

It works for the sample cases and a few other larger cases.

My Code
#include <iostream>
#include <bits/stdc++.h>
#include <cmath>
#include <vector>
#define ll long long int
#define mp make_pair
#define pb push_back
#define vi vector<int>
using namespace std;
const ll p =1e9 + 7;
struct matrix{
    vector<vector<ll>> mat;
    bool isempty=1;
    matrix(int n, int m){
        isempty=0;
        mat.resize(n,vector<ll>(m));
    }
    matrix(){
        mat.resize(2,vector<ll>(2));
        mat[0][0]=1;
        mat[1][1]=1;
    }
    matrix operator*(matrix a){
        matrix ans(this->mat.size(),a.mat[0].size());
        for(int i=0;i<this->mat.size();i++){
            for(int j=0;j<a.mat[0].size();j++){
                for(int k=0;k<a.mat.size();k++){
                    ans.mat[i][j]+=(this->mat[i][k]*a.mat[k][j])%p;
                    ans.mat[i][j]%=p;
                }
            }
        }
        return ans;
    }
    void print(){
        if(isempty){
            return;
        }
        for(int i=0;i<this->mat.size();i++){
            for(int j=0;j<this->mat[0].size();j++){
                cout<<this->mat[i][j]<<" ";
            }
            cout<<'\n';
        }
    }
};
matrix matpower(matrix base,ll power){
    matrix ans(base.mat.size(),base.mat.size());
    for(int i=0;i<base.mat.size();i++){
        ans.mat[i][i]=1;
    }
    while(power){
        if(power & 1){
            ans=ans*base;
        }
        base=base*base;
        power>>=1;
    }
    return ans;
}
vector<matrix> A(20, matrix(2,2));
vector<matrix> B(20, matrix(2,2));
matrix join(matrix a, matrix b){
    return a*b;
}
matrix assign(int h, matrix lazy, matrix seg){
    if(lazy.mat[0][1]==-1){
        return B[h-1];
    }
    return A[h-1];
}
template<typename T>
struct lazy_segment_tree{
    int n;
    int H;
    T base;
    vector<T> segtree;
    vector<T> lazytree;
    T (*join)(T,T);
    T (*assign)(int,T,T);
    lazy_segment_tree(vector<T> &seq, T (*merge)(T,T), T (*create)(int, T,T), T defvalue){
        join=merge;
        assign=create;
        base=defvalue;
        n=seq.size();
        H = sizeof(int) * 8 - __builtin_clz(n);
        segtree.resize(2*n, T());
        lazytree.resize(n, T());
        for(int i=0;i<n;i++){
            segtree[n+i]=seq[i];
        }
        for(int i=n-1;i>=1;i--){
            segtree[i]=join(segtree[(i<<1)], segtree[(i<<1)|1]);
        }
    }
    void calc(int pos, int h){
        if(lazytree[pos].isempty){
            segtree[pos]=join(segtree[(pos<<1)],segtree[(pos<<1)|1]);
        }
        else{
            segtree[pos]=assign(h, lazytree[pos],segtree[pos]);
        }
    }
    void apply(int pos, T value, int h){
        segtree[pos]=assign(h, value, segtree[pos]);
        if(pos<n){
            lazytree[pos]=value;
        }
    }
    void updatenode(int pos){
        int h=1;
        pos+=n;
        while(pos>1){
            h*=2;
            pos>>=1;
            calc(pos, h);
        }
    }
    void push(int pos){
        int h=H;
        int k=1<<(H-1);
        for(pos+=n;h;--h, k>>=1){
            int x=(pos>>h);
            if(!lazytree[x].isempty){
                apply((x<<1), lazytree[x], h);
                apply((x<<1)|1, lazytree[x], h);
                lazytree[x].isempty=1;
            }
        }
    }
    void updaterange(int l, int r, T value){
        push(l);
        push(r-1);
        int k=1;
        int l0=l, r0=r;
        for(l+=n, r+=n;l<r;l>>=1, r>>=1, k++){
            if(l&1){
                apply(l++, value, k);
            }
            if(r&1){
                apply(--r, value,k);
            }
        }
        updatenode(l0);
        updatenode(r0-1);
    }
    T query(int l, int r){
        push(l);
        push(r-1);
        T ansl=base; 
        T ansr=base;
        for(l+=n, r+=n;l<r;l>>=1, r>>=1){
            if(l&1){
                ansl=join(ansl, segtree[l++]);
            }        
            if(r&1){
                ansr=join(segtree[--r], ansr);
            }
        }
        return join(ansl,ansr);
    }
    void printTree(){
        cout<<"SEGMENT TREE:\n";
        for(int i=0;i<2*n;i++){
            cout<<i<<":\n";
            segtree[i].print();
        }
        cout<<"LAZY TREE:\n";
        for(int i=0;i<n;i++){
            cout<<i<<":\n";
            lazytree[i].print();
        }
    }
};
ll solve(){
    int n,Q;
    cin>>n;
    vector<matrix> seq(n);
    for(int i=0;i<n;i++){
        char a;
        cin>>a;
        if(a=='A'){
            seq[i]=A[0];
        }
        else{
            seq[i]=B[0];
        }
    }
    matrix base(2,2);
    base.mat={{1,0},{0,1}};
    lazy_segment_tree<matrix> segtree(seq, join, assign, base);
    cin>>Q;
    for(int i=0;i<Q;i++){
        int type;
        cin>>type;
        if(type==1){
            int l,r;
            char c;
            cin>>l>>r>>c;
            --l;
            if(c=='A'){
                segtree.updaterange(l, r, A[0]);
            }
            else{
                segtree.updaterange(l,r,B[0]);
            }
        }
        else{
            int l,r,P,Q;
            cin>>l>>r>>P>>Q;
            --l;
            matrix ans(1,2);
            ans.mat={{P,Q}};
            ans=ans*segtree.query(l,r);
            cout<<(ans.mat[0][0]+p)%p<<" "<<(ans.mat[0][1]+p)%p<<"\n";
        }
    }
}
void precompute(){
    A[0].mat={{1,1},{-1,1}};
    B[0].mat={{1,-1},{1,1}};
    for(int i=1;i<20;i++){
        A[i]=A[i-1]*A[i-1];
        B[i]=B[i-1]*B[i-1];
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin >>t;
    precompute();
    while(t--){
        solve();
    }
}

Okay i think the only function in my code that may call abort is resize, but I don’t know how to fix it.

Maybe @ssjgz knows why it call SIGABRT?. I tried reading cppreference, but I didn’t understand when it aborts.

The only thing that immediately pops out is that solve is declared to return a ll, but doesn’t return anything.

Beyond that, I’ll have to dig.

3 Likes

Random generation of testcases reveals an out-of-bounds access here:

matrix assign(int h, matrix lazy, matrix seg){
    if(lazy.mat[0][1]==-1){
        return B[h-1];
    }
    return A[h-1]; <-- h = 32; A.size() == 20.
}

Testcase is here (NB: I haven’t checked that the testcase generator generates valid testcases yet!).

2 Likes

Thanks I found the error. h=2^5 gave it away. But why does it abort?

There’s Undefined Behaviour for you :man_shrugging:

2 Likes

How did you get the exact place where it went out of bounds?
I was using
-D_GLIBCXX_DEBUG
and I get this error

Error: attempt to subscript container with out-of-bounds index 5, but 
container only holds 3 elements.

Objects involved in the operation:
    sequence "this" @ 0x0061FED0 {
      type = std::__debug::vector<int, std::allocator<int> >;
    }

How did you know which vector it is and where it was wrongly assigned?
I tried searching and it says to use -g somewhere so I tried to use that
g++ todebug.cpp -o todebug -D_GLIBCXX_DEBUG -g, but I still get the same error.

gdb :slight_smile:

[~/devel/hackerrank/otherpeoples]>gdb ./everule1-ICM2004 
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./everule1-ICM2004...done.
(gdb) r < everule1-ICM2004-testcase-crash.txt
Starting program: /home/simon/devel/hackerrank/otherpeoples/everule1-ICM2004 < everule1-ICM2004-testcase-crash.txt
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
/usr/include/c++/7/debug/vector:417:
Error: attempt to subscript container with out-of-bounds index 31, but 
container only holds 20 elements.

Objects involved in the operation:
    sequence "this" @ 0x0x55555589c780 {
      type = std::__debug::vector<matrix, std::allocator<matrix> >;
    }

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff6762801 in __GI_abort () at abort.c:79
#2  0x00007ffff7ada789 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00005555555dc86e in std::__debug::vector<matrix, std::allocator<matrix> >::operator[] (this=0x55555589c780 <A>, __n=<optimised out>) at /usr/include/c++/7/debug/vector:417
#4  0x00005555555b9b4c in assign (h=32, lazy=..., seg=...) at everule1-ICM2004.cpp:72
#5  0x00005555555e0c04 in lazy_segment_tree<matrix>::calc (this=0x7fffffffd9a0, pos=<optimised out>, h=32) at everule1-ICM2004.cpp:103
#6  0x00005555555cb18c in lazy_segment_tree<matrix>::updatenode (pos=3865, this=0x7fffffffd9a0) at everule1-ICM2004.cpp:118
#7  lazy_segment_tree<matrix>::updaterange (value=..., r=<optimised out>, l=<optimised out>, this=0x7fffffffd9a0) at everule1-ICM2004.cpp:146
#8  solve () at everule1-ICM2004.cpp:204
#9  0x00005555555b6e05 in main (argc=<optimised out>, argv=<optimised out>) at everule1-ICM2004.cpp:285
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22529] will be killed.

Quit anyway? (y or n) y
2 Likes

Could you help me a bit. I’m trying my best :confounded:

PS C:\Users\Public\My codes> g++ todebug.cpp -o todebug -D_GLIBCXX_DEBUG
PS C:\Users\Public\My codes> gdb .\todebug
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\Users\Public\My codes\todebug.exe...done.
(gdb) r < input.txt
Starting program: C:\Users\Public\My codes/.\todebug.exe < input.txt
[New Thread 14020.0x56c8]
[New Thread 14020.0x43d4]
[New Thread 14020.0x48f8]
[New Thread 14020.0x48c4]
c:\users\rashmi jain\downloads\mingw\lib\gcc\mingw32\6.3.0\include\c++\debug\vector:415:
Error: attempt to subscript container with out-of-bounds index 5, but
container only holds 3 elements.

Objects involved in the operation:
    sequence "this" @ 0x0061FED0 {
      type = std::__debug::vector<int, std::allocator<int> >;
    }
[Inferior 1 (process 14020) exited with code 03]
(gdb) bt
No stack.
(gdb) 

When i typed bt I get no stack. I’ll be able to debug my codes myself much better if you would help me out with this.

Hmmm … not quite sure what’s happening, there - it looks like the executable is crashing, but instead of pausing and allowing you to gather a backtrace, gdb is just killing the exe straight away.

Try re-compiling todebug.exe with the -g3 flag.

1 Like

Like this?

g++ todebug.cpp -o todebug -D_GLIBCXX_DEBUG -g3

That didn’t do anything either. I’m trying to debug the simplest code possible, So I can understand how to debug.

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void solve(){
    vector<int> seq(3);
    int x;
    cout<<seq[5];
    cin>>x; 
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}

Hmmm … no idea, I’m afraid: I get:

[simon@simon-laptop][15:17:53]
[~/devel/hackerrank/otherpeoples]>cat todebug.cpp 
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void solve(){
    vector<int> seq(3);
    int x;
    cout<<seq[5];
    cin>>x; 
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}
[simon@simon-laptop][15:17:58]
[~/devel/hackerrank/otherpeoples]>g++ todebug.cpp -o todebug -D_GLIBCXX_DEBUG -g3
[simon@simon-laptop][15:18:02]
[~/devel/hackerrank/otherpeoples]>gdb ./todebug 
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./todebug...done.
(gdb) r
Starting program: /home/simon/devel/hackerrank/otherpeoples/todebug 
/usr/include/c++/7/debug/vector:417:
Error: attempt to subscript container with out-of-bounds index 5, but 
container only holds 3 elements.

Objects involved in the operation:
    sequence "this" @ 0x0x7fffffffdbc0 {
      type = std::__debug::vector<int, std::allocator<int> >;
    }

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff7483801 in __GI_abort () at abort.c:79
#2  0x00007ffff7ada789 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x0000555555555739 in std::__debug::vector<int, std::allocator<int> >::operator[] (this=0x7fffffffdbc0, __n=5) at /usr/include/c++/7/debug/vector:417
#4  0x0000555555555110 in solve () at todebug.cpp:7
#5  0x00005555555551b5 in main () at todebug.cpp:13
(gdb) 

(I didn’t bother to read in the input as your program crashes without it).

Might be because I’m using Linux, perhaps.