怎样C++程序执行过程中的异常?
比如malloc new 申请内存失败?
fopen失败等
并且要把这些报错信息写入一个日志文件
就和java的try 一样?怎样搞搞呢?
谢谢
[解决办法]
windows下还是用SEH来实现异常
[解决办法]
失败了都会有异常或错误代码的,严格检测,遇到有问题就写日志呗。
[解决办法]
一般情况下,执行过程异常都是把相关操作伪码写入日志里的!
打开日志文件应该不会失败吧!
不过代码过程中最好尽量减少这些不必要的bug!
[解决办法]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#define CRITICAL_SECTION pthread_mutex_t
#define _vsnprintf vsnprintf
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
struct tm *now;
struct timeb tb;
if (NULL==pszFmt
[解决办法]
0==pszFmt[0]) return;
_vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
ftime(&tb);
now=localtime(&tb.time);
sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec );
sprintf(mss,"%03d",tb.millitm);
printf("%s %s.%s %s",datestr,timestr,mss,logstr);
flog=fopen(logfilename1,"a");
if (NULL!=flog) {
fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
if (ftell(flog)>MAXLOGSIZE) {
fclose(flog);
if (rename(logfilename1,logfilename2)) {
remove(logfilename2);
rename(logfilename1,logfilename2);
}
} else {
fclose(flog);
}
}
}
void Log(const char *pszFmt,...) {
va_list argp;
Lock(&cs_log);
va_start(argp,pszFmt);
LogV(pszFmt,argp);
va_end(argp);
Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
int i;
#ifdef WIN32
InitializeCriticalSection(&cs_log);
#else
pthread_mutex_init(&cs_log,NULL);
#endif
for (i=0;i<10000;i++) {
Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
}
#ifdef WIN32
DeleteCriticalSection(&cs_log);
#else
pthread_mutex_destroy(&cs_log);
#endif
return 0;
}
//1-78行添加到你带main的.c或.cpp的那个文件的最前面
//81-85行添加到你的main函数开头
//89-93行添加到你的main函数结束前
//在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中
#include <stdio.h>
#include <malloc.h>
void main( void )
{
char *string;
/* Allocate space for a path name */
string = malloc( _MAX_PATH );
if( string == NULL )
printf( "Insufficient memory available\n" );
else
{
printf( "Memory space allocated for path name\n" );
free( string );
printf( "Memory freed\n" );
}
}
Output
Memory space allocated for path name
Memory freed
Memory Allocation Routines
See Also calloc, free, realloc
[解决办法]
new Operator
The new operator attempts to dynamically allocate (at run time) one or more objects of type-name. The new operator cannot be used to allocate a function; however, it can be used to allocate a pointer to a function.
Syntax
allocation-expression :
::opt new placementopt new-type-name new-initializeropt
::opt new placementopt ( type-name ) new-initializeropt
placement :
( expression-list )
new-type-name :
type-specifier-list new-declaratoropt
The new operator is used to allocate objects and arrays of objects. The new operator allocates from a program memory area called the “free store.” In C, the free store is often referred to as the “heap.”
When new is used to allocate a single object, it yields a pointer to that object; the resultant type is new-type-name * or type-name *. When new is used to allocate a singly dimensioned array of objects, it yields a pointer to the first element of the array, and the resultant type is new-type-name * or type-name *. When new is used to allocate a multidimensional array of objects, it yields a pointer to the first element of the array, and the resultant type preserves the size of all but the leftmost array dimension. For example:
new float[10][25][10]
yields type float (*)[25][10]. Therefore, the following code will not work because it attempts to assign a pointer to an array of float with the dimensions [25][10] to a pointer to type float:
float *fp;
fp = new float[10][25][10];
The correct expression is:
float (*cp)[25][10];
cp = new float[10][25][10];
The definition of cp allocates a pointer to an array of type float with dimensions [25][10] — it does not allocate an array of pointers.
All but the leftmost array dimensions must be constant expressions that evaluate to positive values; the leftmost array dimension can be any expression that evaluates to a positive value. When allocating an array using the new operator, the first dimension can be zero — the new operator returns a unique pointer.
The type-specifier-list cannot contain const, volatile, class declarations, or enumeration declarations. Therefore, the following expression is illegal:
volatile char *vch = new volatile char[20];
The new operator does not allocate reference types because they are not objects.
If there is insufficient memory for the allocation request, by default operator new returns NULL. You can change this default behavior by writing a custom exception-handling routine and calling the _set_new_handler run-time library function with your function name as its argument. For more details on this recovery scheme, see The operator new Function.
Handling Insufficient Memory Conditions
Testing for failed memory allocation can be done with code such as the following:
int *pi = new int[BIG_NUMBER];
if( pi == 0 )
{
cerr << "Insufficient memory" << endl;
return -1;
}
There is an other ways to handle failed memory allocation requests: write a custom recovery routine to handle such a failure, then register your function by calling the _set_new_handler run-time function. This method is described in the following section.
_doserrno, errno, _sys_errlist, and _sys_nerr
These global variables hold error codes used by the perror and strerror functions for printing error messages. Manifest constants for these variables are declared in STDLIB.H as follows:
extern int _doserrno;
extern int errno;
extern char *_sys_errlist[ ];
extern int _sys_nerr;
errno is set on an error in a system-level call. Because errno holds the value for the last call that set it, this value may be changed by succeeding calls. Always check errno immediately before and after a call that may set it. All errno values, defined as manifest constants in ERRNO.H, are UNIX-compatible. The values valid for 32-bit Windows applications are a subset of these UNIX values.
On an error, errno is not necessarily set to the same value as the error code returned by a system call. For I/O operations only, use _doserrno to access the operating-system error-code equivalents of errno codes. For other operations the value of _doserrno is undefined.
Each errno value is associated with an error message that can be printed using perror or stored in a string using strerror. perror and strerror use the _sys_errlist array and _sys_nerr, the number of elements in _sys_errlist, to process error information.
Library math routines set errno by calling _matherr. To handle math errors differently, write your own routine according to the _matherr reference description and name it _matherr.
The following errno values are compatible with 32-bit Windows applications. Only ERANGE and EDOM are specified in the ANSI standard.
Constant System Error Message Value
E2BIG Argument list too long 7
EACCES Permission denied 13
EAGAIN No more processes or not enough memory or maximum nesting level reached 11
EBADF Bad file number 9
ECHILD No spawned processes 10
EDEADLOCK Resource deadlock would occur 36
EDOM Math argument 33
EEXIST File exists 17
EINVAL Invalid argument 22
EMFILE Too many open files 24
ENOENT No such file or directory 2
ENOEXEC Exec format error 8
ENOMEM Not enough memory 12
ENOSPC No space left on device 28
ERANGE Result too large 34
EXDEV Cross-device link 18
[解决办法]
用try catch抓 ,在catch里处理