|
shouldn't try...catch catch only C++ exceptions? An access violation is a crash, not an exception.
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|
|
As far as i know access violation raises an exception, the crash occurs if this exception is nowhere cought in the program itself. I did use try...catch to catch access violations in the past and it worked fine, althorough doing so isn't a very..."nice" solution, but sometimes it can be necesarry.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Computers are evil, EVIL i tell you!! <
|
|
|
|
|
Yeah. I thought, that the CException class should be able to catch all the exceptions.
But in my example, the app crashes without the exception being caught.
Im looking for a way to be able to catch that exception.
|
|
|
|
|
I was talking about the "not nice" part too. That's why I called it crash not exception. IMHO C++ exceptions should be an error reporting mechanism, whereas an access violation means your program just got corrupted.
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|
|
True, but he asked how he could catch that exception, that is a way.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Computers are evil, EVIL i tell you!! <
|
|
|
|
|
Tried this, but it is giving errors as "not enough actual parameters for macro 'CATCH'"
|
|
|
|
|
Try this way then
void DoSomething()
{
ItemNode *a = NULL;
try {
CString s;
s.Format (_T("%s"), a->szID);
}
catch(...){
MessageBox (_T("Exception occured"));
}
}
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Computers are evil, EVIL i tell you!! <
|
|
|
|
|
catch( ... ) is generally a really bad idea, it just eats anything and doesn't really tell you a lot. About the only place you should use it is around main so you at least get a hint that something out of the ordinary has occured and you've got a well serious problem:
int main()
try
{
}
catch( std::exception &e )
{
std::cout << "An error occurred: " << e.what() << std::endl;
}
catch( ... )
{
std::cout << "An error occurred: No idea what!" << std::endl;
}
Cheers,
Ash
PS: Using catch( ... ) around thread functions, message handlers and module boundaries can also be good as you don't want to throw through C-style or OS interfaces.
|
|
|
|
|
|
Tried this also...
Still the app shows "Encountered a problem and needs to close..."
Not able to see the messagebox.
|
|
|
|
|
Well, what is MessageBox anyways? IS it your own method? I mean, the MessageBox[^] method in the docs requires more than a string.
Anyways, if i put this in the InitInstance of a test app it displays me the message box as it should.
try {
char *c = NULL;
*c = 3;
} catch (...)
{
AfxMessageBox("Yikes");
}
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Computers are evil, EVIL i tell you!! <
|
|
|
|
|
To catch access violations and such, you need to use Win32 structured exception handling, like __try __except
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
modified on Friday, May 28, 2010 8:12 AM
|
|
|
|
|
VC++ has a method of converting structured exceptions into C++ exceptions( _se_set_translator() IIRC). It's handy to be able to converge SEH and C++ exceptions into the same handler - provided some muppet doesn't use it as a way to keep code limping along after a null pointer dereference.
Cheers,
Ash
|
|
|
|
|
A small code snippet would be very helpful
Or, can you post how to use the _se_set_translator(), according to the snippet i posted.
|
|
|
|
|
In general catching access violations is the wrong thing to do. If the access violation is coming from inside the TRY block in the code you posted it's more than just "the wrong thing to do", it's sheer madness. Find the real problem! Where exactly in the code is the crash?
Steve
|
|
|
|
|
|
No ... that's not a good solution.
If the file is corrupted you must be able to understand the corruption while reading the file, and throw yourself an exception if you cannot recover (and then handle the exception properly)
Doing the way you think may not working as expected.
If you are lucky, some pointer can be null, and an hardware exception is thrown during dereference, and you can catch it either using catch(...) or using the OS API support.
But if you're not, some pointer may be wrong, but still valid (I mean: pointing to something different to what it should be expected, but still inside your program memory space), hence dereferencing them doesn't throw anything. It simple made wrong results the user may even not recognize (and are the most subtle bug to fix).
Catching a bad dereference in case of data corruption to avoid a crash is not the solution. It's just an illusion to solve the problem, that may have also other consequences.
2 bugs found.
> recompile ...
65534 bugs found.
|
|
|
|
|
The problem is that an access violation isn't error reporting - it means that your program has memory corruption. There is a difference. An access violation ALWAYS means that your code isn't well done. You should simply change your code to avoid an access violation occurring at all. Fix your code. Debug your program, find where you access the NULL pointer, and put something like this:
if (ptr) {
ptr->szID;
}
else
throw std::exception("The pointer is NULL!");
If you really want exceptions, that's the way you do it. An exception is something you "throw". An access violation isn't an exception - it's a crash.
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|
|
You've been told by basically every reply that using exceptions to catch access-violations is almost certainly a bad design. This is why standard compliant compilers don't allow it. If you insist on ignoring the advice, I guess there's isn't a lot more we can do. In the link you gave you said you can't check for NULLs yourself. Why not?
Steve
|
|
|
|
|
Hi all,
i am trying to display a image in dialog box. i have used this code to do it so far.
CString szFilename ("C:\\abc.bmp");
HBITMAP hBmp = (HBITMAP)::LoadImage(
NULL,
szFilename,
IMAGE_BITMAP,
0,
0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION
);
m_st_pic.SetBitmap(hBmp);
My problem is i want to resize my image that is i want to display it according to a particular size...
but i am not getting how to do it...
Can anybody help in this...
|
|
|
|
|
I'm probably not completely aware of all the bitmap-sizing capabilities of the static control (i assume your m_st_pic is a static) but you could try drawing the bitmap in your dialog's OnPaint and use StretchBlt[^] to size it to whatever size you want to.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Computers are evil, EVIL i tell you!! <
|
|
|
|
|
You should display the image (properly resized) in the WM_PAINT message handler (see, for instance, "Scaling an Image").
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
|
I have a C program, which has to be compiled in VS.NET 2005 environment. I don't have any issues with the compilation part and the EXE is generated. When I run the EXE the program is looping. Pls find below the source code:
/* ------------------------------------------------------------------------ */
/* Program Name : GLDBACK2.C */
/* Last Modified : 03/11/08 - RMC - Creation date */
/* N.B. GLD0DETL has 190 fields and is 1287 bytes */
/* */
/* ------------------------------------------------------------------------ */
/************************************************************************** */
/* Reads dBase file and outputs as text file. */
/* Based on Valour Software freeware. */
/************************************************************************** */
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct dbase_head {
unsigned char version; /*03 for dbIII and 83 for dbIII w/memo file*/
unsigned char l_update[3]; /*yymmdd for last update*/
unsigned long count; /*number of records in file*/
unsigned int header; /*length of the header
*includes the \r at end
*/
unsigned int lrecl; /*length of a record
*includes the delete
*byte
*/
unsigned char reserv[20];
} DBASE_HEAD;
typedef struct dbase_fld {
char name[11]; /*field name*/
char type; /*field type*/
#define DB_FLD_CHAR 'C'
#define DB_FLD_NUM 'N'
#define DB_FLD_LOGIC 'L'
#define DB_FLD_MEMO 'M'
#define DB_FLD_DATE 'D'
/* A-T uses large data model but drop it for now */
//char far *data_ptr; /*pointer into buffer*/
unsigned char length; /*field length*/
unsigned char dec_point; /*field decimal point*/
unsigned char fill[14];
} DBASE_FIELD;
typedef struct fld_list {
struct fld_list *next;
DBASE_FIELD *fld;
char *data;
} FLD_LIST;
DBASE_HEAD dbhead={0};
FLD_LIST *db_fld_root=0;
char *Buffer;
char buf_work[255];
int dbfile;
int ck, fldtotal;
unsigned long reccount;
int fldcount=0;
FILE *outtxt, *infotxt;
char OUTNAME[50]= "";
char INFONAME[50]= "";
char *outf, *infof;
char *envSys;
char *envBrNo;
/*------------------------------------------------------------code-------*/
main(argc,argv)
int argc;
char *argv[];
{
printf("\nGLDBACK2\n");
if(argc!=2)
emessage("Usage is db_dump","filename.dbf", -1);
envSys = getenv("SYS");
envBrNo = getenv("BRN");
outf = OUTNAME;
infof = INFONAME;
sprintf(outf, "H:\\%s\\DATA\\BRANCH%s\\DATALOC\\glddbf.txt",envSys,envBrNo);
sprintf(infof, "H:\\%s\\DATA\\BRANCH%s\\DATALOC\\gldinfo.txt",envSys,envBrNo);
outtxt = fopen(OUTNAME,"w");
if (outtxt == 0)
{
emessage("Opening","glddbf", outtxt);
exit(2);
}
infotxt = fopen(INFONAME,"w");
if (infotxt == 0)
{
emessage("Opening","gldinfo", infotxt);
exit(2);
}
dbfile=open(argv[1],O_RDONLY);
if(dbfile==-1)
{emessage("Unable to open file",argv[1], -1);}
/* read data dictionary */
printf("Reading data dictionary\n");
db3_read_dic();
/* write out records */
printf("Writing records...\n");
db3_print_recs();
printf("\n\nProcessing complete\n");
close(dbfile);
exit(0);
/* Close output text file */
ck=fclose(outtxt);
if (ck != 0)
{
emessage("Closing","glddbf",ck);
exit(2);
}
}
/******************************************************
db3_read_dic()
This function is called with a file name to
read to create a record type to support the
dbase file
******************************************************/
db3_read_dic()
{
int fields;
DBASE_FIELD *fld;
if(dbfile==-1) {
printf("open failed");
exit(200);
}
read(dbfile,&dbhead,sizeof(DBASE_HEAD));
if( !(dbhead.version==3 || dbhead.version==0x83) )
{
printf("\n\aVersion %d not supported",dbhead.version);
emessage("Version not","supported", -1);
}
fprintf(infotxt, "update year %3d",dbhead.l_update[0]);
fprintf(infotxt, "update mon %3d",dbhead.l_update[1]);
fprintf(infotxt, "update day %3d",dbhead.l_update[2]);
fprintf(infotxt, "number of recs %6u",dbhead.count);
reccount = dbhead.count;
fprintf(infotxt, "header length %3d",dbhead.header);
fprintf(infotxt, "record length %3d\n",dbhead.lrecl);
Buffer=malloc(dbhead.lrecl);
printf("\nHeader reccount = %6u\n", reccount);
fldtotal = 0;
fields=(dbhead.header-1)/32-1;
fprintf(infotxt, "Field Name\tType\tLength\tDecimal Pos\n");
while(fields--) {
fld=(DBASE_FIELD *)malloc(sizeof(DBASE_FIELD));
if(!fld)
emessage("Not enough memory","DBASE_FIELD", -1);
read(dbfile,fld,sizeof(DBASE_FIELD));
fprintf(infotxt, "%-10s\t %c\t %3d\t %3d\n",fld->name,fld->type,
fld->length,fld->dec_point);
++fldtotal;
stack_field(fld);
}
read(dbfile,Buffer,1); /*read the silly little \r character*/
printf("Number of fields = %6d\n", fldtotal);
/* Close info text file */
ck=fclose(infotxt);
if (ck != 0)
{
emessage("Closing","gldinfo",ck);
exit(2);
}
return;
}
/******************************************************
db3_print_recs()
Read records and print the data
******************************************************/
db3_print_recs()
{
int bytes;
unsigned long readcnt=0;
int maxflag=0; /* max count = 65536 */
double maxcnt=0;
while(Buffer[0]!='*')
{
bytes=read(dbfile,Buffer,dbhead.lrecl);
if(bytes!=dbhead.lrecl)
break;
if(Buffer[0]!='*') {
db3_print();
++readcnt;
if(readcnt==65536)
{
printf("\ncount boundary reached\n");
maxflag=1;
}
printf("Writing record number %6u\r", readcnt);
}
}
if(maxflag==1)
{
maxcnt = readcnt;
printf("\nFinal number written is %0.6f\n", maxcnt);
}
return;
}
/******************************************************
db3_print()
Print a single record
******************************************************/
db3_print()
{
FLD_LIST *list, *temp;
temp=db_fld_root;
while(temp) {
memcpy(buf_work,temp->data,temp->fld->length);
++fldcount;
buf_work[temp->fld->length]='\0';
if (fldcount==fldtotal)
{fldcount=0;
fprintf(outtxt,"%s\n",buf_work);}
else
{fprintf(outtxt,"%s",buf_work);}
temp=temp->next;
}
return;
}
/******************************************************
stack_field()
Add a field to the linked list of fields
******************************************************/
stack_field(fld)
DBASE_FIELD *fld;
{
FLD_LIST *list, *temp;
list=(FLD_LIST *)calloc(1,sizeof(FLD_LIST));
if(!list)
emessage("Not enough memory","FLD_LIST", -1);
list->fld=fld;
if(!db_fld_root) {
list->data=Buffer+1; /*skip delete byte*/
db_fld_root=list;
return;
}
temp=db_fld_root;
while(temp->next)
temp=temp->next;
temp->next=list;
list->data=temp->data + temp->fld->length;
return;
}
/***********************/
/* emessage routine */
/***********************/
emessage(edesc,efile,ecode)
char edesc[7];
char efile[8];
int ecode;
{
printf ("\n\n***************************************************************\n");
printf ("** **\n");
printf ("** Error %s %s file. Status = %2d **\n",edesc,efile,ecode);
printf ("** **\n");
printf ("** Print This Screen and **\n");
printf ("** **\n");
printf ("** PLEASE CALL LONDON SUPPORT **\n");
printf ("** **\n");
printf ("***************************************************************\n");
printf("\nPress any key to continue ");
getchar();
return (9);
}
/* End of program */
The function db3_read_dic() is reading a .DBF file and writing the header details to a .TXT file. In that process, the record length is 0. The same EXE generated from MC6 environment works fine. But when the program is being compiled in VS.NET, it loops. Any idea?
|
|
|
|
|
Some suggestions:
- Please use the pre tag to format your code properly. As it is now, it is barely readable.
- What do you mean by "it loops" exactly ? Is it hanging ?
- Did you try to use your debugger to track down the problem ?
|
|
|
|
|