0

In an attempt to build a matrix on my small computer, the array size becomes big, it goes out memory capacity and then I got a segv, I want to know if there a way in C++ to detect segv without jumping out and then continue?

unsigned m = 10000;
unsigned n = 10000;
double mat[m][n];
for (unsigned i = 0; i < m; ++i)
{
    for (unsigned j = 0; j < n; ++j)
    {
        double tmpNum1 = rand()%precisionA;
        double tmpNum2 = tmpNum1/precisionA+rand()%precisionB;

        mat[i][j] = tmpNum2;
    }
}

if (segv) // How to do this???
{
    cout<< "Buy a new computer please!" << endl;
}
else
{
    cout<< "Good, get a coffee for yourself!" << endl;
}

Edit1: Sometimes the error is segv, sometimes it is "terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped)" Edit2: Using Ubuntu here.

Daniel
  • 2,576
  • 7
  • 37
  • 51
  • Either use new to do dynamic allocation, or, as you requested, try-catch the seg fault. http://stackoverflow.com/questions/2350489/how-to-catch-segmentation-fault-in-linux – digit plumber Apr 17 '14 at 19:06
  • I think you could install a [signal handler](http://linux.die.net/man/2/signal) to catch it. – πάντα ῥεῖ Apr 17 '14 at 19:10

4 Answers4

8

An array of 10000x10000 doubles is about 800MB, and you are putting that array entirely on the stack. So, of course it will SEGV: no system I know of allocates nearly a GB of stack memory.

Allocate this on the heap instead using new and it should work fine.


As for how to catch a SEGV, this is platform-specific. A SEGV is, in some sense, one of many possible responses to undefined behaviour caused by your program. Catching a SEGV by no means catches all possible ways your program could fail from this undefined behaviour.

On Windows, you may use a structured exception handler to catch the Access Violation exception that is thrown by the invalid access.

On POSIX systems, you may use a signal handler to catch a SIGSEGV.

But, keep in mind, there are other ways your program can die because of a stack overflow (which is what happens in this case). Your stack might grow so far down that it intersects with the heap, causing heap corruption; your OS might not catch the invalid access and crash much later on with an unrelated error; libc might call abort() after detecting a stack smash, or any number of other errors. Therefore, the best way to catch a SEGV is to fix it in the first place.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • Okay, my question is how to tell C++ that segv happens? – Daniel Apr 17 '14 at 19:04
  • @Daniel There is, on POSIX systems (like Linux or OSX) a signal you can catch. But there is seldom anything to do as when you get it and it's very likely that your program is in such a state it can't continue anyway. – Some programmer dude Apr 17 '14 at 19:06
  • @cppinitiator `try catch` only catches C++ exceptions, not program crashes like segmentation fault. – Some programmer dude Apr 17 '14 at 19:08
  • I know, I always use std::vector extensively now. I am just curious to know how to catch the exception. Thanks though – Daniel Apr 17 '14 at 19:08
  • @Daniel on windows use SEH (structured exception handling), on linux use signals - search google for signal handlers. – marcinj Apr 17 '14 at 19:10
  • Thank you. Just a quick question before you leave, to see if you have a quick explanation. I am testing a matrix summation calculation `sum += mat[i][j]` using two methods, method-1: `double** mat = new double*[m]` and method-2: `vector > mat;`, do you know why summation using method-2 is lots slower than method-1? – Daniel Apr 17 '14 at 19:22
2

You can use the signal() function to intercept a signal such as SIGSEGV:

http://www.cplusplus.com/reference/csignal/signal/

Please note that in your case, you are allocating your matrix onto the stack of your program, which is rather small (It is around 8MB or so on Linux).

You may want to allocate your matrix using dynamic allocation ( the new operator). Doing so will store your matrix into the heap of your program, where you can store a lot more data.

Shuny
  • 175
  • 1
  • 7
1

To catch heap allocation failures caused by operator new (C++), you need to enclose the call to it on a try/catch block then capture the std::bad_alloc exception.

If you allocate your memory with malloc()/calloc() and friends, just check the return value. It will be NULL on error or allocation failure.

For stack-overflows, caused either by recursion, large stack allocated arrays or alloca(), there are two ways to handle the exception that I know of. On Windows, you can use Structured Exception Handling (SEH). The other way is to use the C Signals API.

glampert
  • 4,371
  • 2
  • 23
  • 49
-1

Your mat array is invalid C++.
Use new/delete, or std::array, std::vector...
Then you can catch the expection std::bad_alloc

(and i understand what you mean, but why the word "segv" ?)

deviantfan
  • 11,268
  • 3
  • 32
  • 49
  • _'Your mat array is invalid C++.'_ Shouldn't the compiler complain then? I see allso no UB here. – πάντα ῥεῖ Apr 17 '14 at 19:06
  • well, `unsigned m` should IMO opinion be `const unsigned m`, because now mat looks like variable length array which is non standard – marcinj Apr 17 '14 at 19:08
  • @πάνταῥεῖ I didn´t said anything about UB. But not too long ago someone (could be even you) showed me that VLAs are not valid... – deviantfan Apr 17 '14 at 19:09
  • @deviantfan Don't remember what you're referring, but you can't generalize _'is invalid C++'_ for the question this way. Also the OP asks how to catch this error, not how to avoid it. – πάντα ῥεῖ Apr 17 '14 at 19:13
  • Using `std::array` or `std::vector` is only going to help so much in avoiding a segment fault. If you access an element outside the range of the vector or array you're just as prone to having a segfault as if you were using a plain old naked array. – Captain Obvlious Apr 17 '14 at 19:16