I allocate a char pointer for receiving data. When the data is too large, I'll receive the Segmentation fault (core dumped). I try to use a try catch block to catch the exception to avoid this kind of error, but the same error still shows. How do I catch this kind of exception?
#include<iostream>
using namespace std;
void setmemory(char* p, int num)
{
p=(char*)malloc(num);
}
void test(void)
{
char* str = NULL;
setmemory(str,1);
try{
strcpy(str,"hello");
cout << "str:" << str << endl;
} catch (...) {
str = NULL;
cout << "Exception occured!" << endl;
}
}
int main()
{
test();
return 0;
}
Generally catching of Segmentation Fault is bad idea because you have no guaranty that any data in your program still valid. So you cannot just intercept SIGSEGV signal and do you work as usual.
See more details here:
How to catch segmentation fault in Linux?
You cannot catch segmentation fault through exception... Exceptions are not designed to catch signals. For these cases you need special handling like calling signal handler etc...
Although there is a way to convert these signals into exceptions in C++. Following link would illustrate on this topic:-
https://code.google.com/p/segvcatch/
Example given in this:-
try
{
*(int*) 0 = 0;
}
catch (std::exception& e)
{
std::cerr << "Exception catched : " << e.what() << std::endl;
}
Anyway after getting segmentation fault it's better to go for debugging rather than continue with current execution and later be transported to realm of undefined behavior.
You cannot catch a Segmentation fault in C++. A seg fault is a result of memory corruption due to a bad operation run by your program. At that point, the operating system has taken control of your program. You don't want to keep a program running after a seg fault because the state is unstable. You as the programmer need to avoid seg faults.
If the code you posted is your actual code, even if you allocated enough space, your code will not work correctly.
void setmemory(char *p, int num)
{
p=(char*)malloc(num);
}
int main()
{
char* str = NULL;
setmemory(str,1);
//...
strcpy(str,"hello");
We can stop right there. You are attempting to copy "hello" to a NULL pointer. You are not setting str to the allocated space, even though the setmemory function was called.
The proper way to do this (I will use the malloc, even though I don't recommend it) would be:
void setmemory(char *&p, int num)
{
p=(char*)malloc(num);
}
You need to pass the pointer by reference, otherwise p acts as a temporary variable, so setting p within the function will not propagate back to the caller.
Related
I am solving a problem on codechef.
I have coded the algorithm of the problem and it runs fine on the test cases. Although, when I run it on codechef(online), it throws segmentation fault.
I have double checked that, I am not accessing any inaccessible memory locations, although I suspect that my program could have taken up huge amount of memory.
So, my question is that Can segmentation fault be thrown, when there is no more memory available for the program to execute. Something like OutOfMemoryException in C#
This depends on the way you allocate memory and whether you check for errors when doing so. E.g. malloc would return NULL on an out-of-memory condition. A failure to check that may lead to dereferencing NULL which would result in a segmentation fault. If you use new of C++, it would throw an exception instead.
In reality though when a program does excessive memory allocations it usually gets the system RAM overcommitted and its process is killed by an OOM killer before its malloc would start returning NULLs - unless most of the allocated memory is actually unused.
As Kerrek mentioned in the comments an excessive usage of automatic storage or a call stack which is too deep can cause a SEG-fault e.g (on coliru):
void foo(){ foo(); }
int main() {
foo();
return 0;
}
or (on coliru):
#include <iostream>
int main()
{
int a[50000000];
std::cout << a[500];
}
So to sum it up you have to be aware of your systems limitations, for example some recursive brute force solutions are sometimes theoretically OK and should work but are rather impractical (yes, this is a vague example but the OP did not mention what problem is being solved nor how so I wanted to give the above at least some context...).
There are actually two situations
1. You try to allocate too much from the call stack, then you'll receive a signal. An exception can't be caught
int main() {
try {
std::array<int,10000000> arr;
cout << arr[40] << endl;
}
catch(const std::exception& e) {
cout << e.what() << endl;
}
return 0;
}
2. You try to allocate too much dynamic memory, then you'll receive an exception
int main() {
try {
std::vector<int> arr;
arr.resize(1000000000);
cout << arr[40] << endl;
}
catch(const std::exception& e) {
cout << e.what() << endl;
}
return 0;
}
You can try it live on ideone.
What does throw do when not used with try and catch? Like:
if (IsEmpty()) throw "Stack is empty, Cannot delete";
Does it get printed in console?
But when throw contains some int or char as its arguments, it is thrown to catch; what happens in this case?
The C++ runtime will have something along the lines of (this is NOT exactly how it looks, but you can think of it as working this way, unless you are working on something very special):
void BeforeMain()
{
try
{
int res = main();
exit(res);
}
catch(...)
{
cout << "Unhandled exception. Terminating..." << endl;
terminate();
}
}
You are allowed to do that, and it will not be caught anywhere within your code if you have not put an explicit try catch block.
Windows uses a SEH mechanism to handle , where you could have an uncaught exception filter to figure out about the same
See this post for more details
Catching exceptions thrown without try/catch
gcc (GCC) 4.5.3
GNU gdb (GDB) 7.5.50.20130309-cvs (cygwin-special)
Netbeans 7.3
I have some trouble catching a SIGSEGV, Segment Fault Exception, in my code. A try-catch does not catch it (code below). Is this a non-catchable exception? Is there any way to catch it? (And of Course) What have I done wrong?
art
string SlipStringOp::dump(const SlipCell& X) const {
stringstream pretty;
PTR ptr = *getPtr(X);
pretty << "[string ] " << dumpLink(X) << " = "
<< setfill('0') << setw(8) << hex << ptr
<< " -> ";
try {
pretty << ptr->dump();
} catch(exception& e) {
pretty << e.what();
postError(SlipErr::E3023, "SlipStringOp::dump", "", "Deletion of cell deleted the pointer.");
} catch(...) {
postError(SlipErr::E3023, "SlipStringOp::dump", "", "Deletion of cell deleted the pointer.");
}
return pretty.str();
}; // string SlipStringOp::dump(const SlipCell& X) const
SIGSEGV is not an exception; it's a signal. Accessing an invalid memory address is known as a segmentation fault. When your program does this, the operating system will send your process the SIGSEGV signal. The default handler for this signal will immediately terminate the process.
You can intercept a signal, but this is not a signal you should be handling yourself. If your program is causing a segmentation fault, it has a bug, no doubt about it.
If you've isolated the segmentation fault to the pretty << ptr->dump(); line, I would guess that the problem is probably that ptr isn't pointing to a valid object. Alternatively, the dump function is doing something bad.
Do not attempt to fix this by handling the signal. Do fix this by making sure your program doesn't cause a segmentation fault.
There are two questions here. Firstly, why are you getting a SIGSEGV? There probably isn't enough code here for us to tell, but is your call to ptr->dump() calling the same function recursively? IF so, you have infinite recursion, and that is causing the seg fault.
Second question is how you trap the signal, and that's been answered by previous responders.
You throw an exception with a throw expression. You catch an exception in a catch clause.
You raise a signal by calling raise. You handle a signal by installing a handler before the exception is raised.
Any other actions and interactions are system-specific (i.e., not portable).
In the code below i use try/catch in the python module code. In the try block i have a simple error (memory access violation) and trying to catch the corresponding exception and to terminate the program quietly without generation of the .stackdump file. However the latter is still generated what implies that try/catch construct does not do its job. How could i avoid generating .stackdump file and exit the program without errors when the improper operation (like one in the code) is met?
P.S. i'm compiling the code in cygwin with gcc and boost.python
It is interesting that it doesn't work only in case x[3]=2, but works for all other cases: e.g. x[4]=2 or x[20]=2 or, obviously, x[2]=2.
#include <boost/python.hpp>
#include <iostream>
#include <iomanip>
using namespace std;
using namespace boost::python;
class Hello
{
std::string _msg;
public:
Hello(std::string msg){_msg = msg;}
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ exit(0); }
}
};
BOOST_PYTHON_MODULE(xyz)
{
class_<Hello>("Hello", init<std::string>())
.def("run",&Hello::run)
;
}
EDIT:
According to what Maciek has suggested i tried the following trick:
Make signal handling function to throw an exception, but not exit
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
throw 1;
// exit(0);
}
And now try to enclose a possibly problematic function in try/catch block (signal function is placed in class constructor):
class Hello
{
std::string _msg;
public:
Hello(std::string msg){
_msg = msg;
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
}
void set(std::string msg) { this->_msg = msg; }
std::string greet() { return _msg; }
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ cout<<"error in function run()\n"; exit(0); }
}
};
However such a trick doesn't work as i expected it produces the following output:
SIGNAL 6
terminate called after throwing an instance of 'int'
SIGNAL 6
terminate called recursively
SIGNAL 6
terminate called recursively
....
(and many more times the same)
So the exception is thrown, but everything finishes before it has been caught. Is there any way to let it be caught before terminating the process?
You can only catch exceptions that are thrown. An invalid pointer access doesn’t throw an exception, it simply causes undefined behaviour, and in your particular case it results in a stack dump.
If you want to catch such a situation situation, use std::vector and the at function to access items. This will throw std::out_of_range when used with an invalid index. However, it’s usually better to avoid the possibility of such accesses a priori since they are usually indicative of a bug in your program, and bugs should not be handled via exceptions, they should be removed from the code.
On linux core dumps are generated by signal handlers with default action set to core (SIGABRT, SIGSEGV, ...). If you want to avoid core dump you can always capture/ignore those signals. It should work on Cygwin stackdumps as well. But you will still probably get some nasty message as output.
EDIT:
#include <signal.h>
// [...]
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
exit(0);
}
int main(int argc, char* argv[]) {
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
Hello h("msg");
h.run();
}
I'm trying to safely recover from a segmentation fault I expect to happen. I'm trying to avoid it checking using my canAlloc() function here. When canAllow returns false, A0 (which is Ackermann's if you didn't see it) should throw an exception that I can catch in the main method. checkTable and saveInTable are both functions that use a map<int hash, int value> to store returns from A0.
bool canAlloc(){
bool reBool = false;
int * memch = (int*)calloc (10000, sizeof(int));
reBool = (memch != NULL);
free(memch);
return reBool;
}
int A0(int m, int n){
if(!canAlloc()) throw;
int reInt = checkReturnTable(m,n);
if(reInt == -1){
if(m == 0){
return n + 1;
} else if(m > 0){
if(n == 0){
reInt = A0(m-1,1);
} else if(n > 0){
reInt = A0(m-1, A0(m,n-1));
}
}
saveInReturnTable(m,n,reInt);
return reInt;
} else return reInt;
}
From a comment:
In main I have a try-catch block to catch any exception try{} catch(...){}. As I understand it the three periods should catch any exception thrown. And as I understand, the throw keyword throws the exception without any specifiers, but can still be caught by the three dots.
A segmentation fault is not a C++ exception. It is indicative of a program failure that causes the OS to send a SIGSEGV signal to your process. You won't be able to catch a SIGSEGV signal directly; you'd have to set up a signal handler and ... well, it gets tricky at that point, because it is not clear that you can throw an exception from within a signal handler.
A throw with no exception specified rethrows the current exception; it only makes sense inside a catch block.
You probably get the SIGSEGV when your system is unable to extend the stack any further, probably because you've run out of virtual memory. That means one of your function calls failed because there was no space to put its arguments or local variables or return address, etc. There is no clean way to recover from that, which is why the system generates the segmentation fault.
If the fault was because calloc() could not allocate memory, you'd not get a segmentation fault; you'd get a zero return value. And you could raise an 'out of memory' exception cleanly and synchronously when it happens. But that isn't your problem.
You cannot recover from a segmentation fault, because once the fault occurs, your program is no longer in a well-defined state, and there's no mechanism to roll back to a well-defined state, either.
A segmentation fault is always a programming error in one way or another, and you must simply avoid it. In C++, you can simply catch exceptions coming from a dynamic allocation:
T * p;
try { p = new T; }
catch(const std::bad_alloc & e) { /* ... */ }
Usually there's no need to be quite that manual, though, since you would wrap your dynamic allocations inside suitable managing containers (like unique_ptr or shared_ptr), and you should catch exceptions (not even just allocation ones) at points in your program flow where you are in a position to handle the error and continue meaningfully.
(Thanks to exceptions you should not usually need to check the result of possibly throwing functions right at the call side - that's the whole point of using exceptions.)
If for some reason you just want to allocate raw memory, without constructing any object, you can do it in two ways:
// Method #1, the C++ way:
void * addr = ::operator new(n); // will throw std::bad_alloc on error
// Method #2, the manual way:
void * addr = std::malloc(n);
if (!addr) throw std::bad_alloc(); // throw exception manually, handled elsewhere