Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: try catch problem with TZDecompressionStream


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: May 8, 2017 1:37 AM Last Post By: Oliver Weinheimer
Oliver Weinheimer

Posts: 73
Registered: 8/20/04
try catch problem with TZDecompressionStream  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 3, 2017 2:00 AM
Hi - the following code in a function call works perfect if the loaded compressed file is ok - but if it is corrupted the error is not catched.
In my case the error occurs in unzip->ReadBuffer(dim,3*sizeof(int));
The following catch(...) is never reached.
What is wrong?
(I am on C++Builder Tokyo, bcc64)

--- code

TFileStream *input=0;
try
{
input= new TFileStream(temp_filename.c_str(),
fmOpenRead);
}
catch(...)
{
input = 0;
}

if (input!=0)
{
TZDecompressionStream *unzip = 0;
try {
unzip = new TZDecompressionStream(input);
}
catch(...){
unzip=0;
}

if (unzip!=0)
{
int dim[3];
try{
unzip->ReadBuffer(dim,3*sizeof(int));
}
catch(...){
FILE_LOG(logERROR) << "Reading of decompressed stream fails!";
}
}

Edited by: Oliver Weinheimer on May 3, 2017 3:15 AM
Oliver Weinheimer

Posts: 73
Registered: 8/20/04
Re: try catch problem with TZDecompressionStream  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 3, 2017 3:14 AM   in response to: Oliver Weinheimer in response to: Oliver Weinheimer
After reading about asynchronous exceptions and that these ones are not supported by the clang based compiler I replaced the last catch ad the end of the code by:

__finally{
FILE_LOG(logERROR) << "ReadBuffer failed!";
}
return 0;

This works.
The program returns from the function.
No problems in the program afterwards.

Inside the function, code after the __finally block does not work, just return is possible.
Is that a normal behavior? As I said - main program runs without any problems after the function is left.
Oliver Weinheimer

Posts: 73
Registered: 8/20/04
Re: try catch problem with TZDecompressionStream  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 3, 2017 8:38 AM   in response to: Oliver Weinheimer in response to: Oliver Weinheimer
My first reply was wrong.
Did not work.

My solution for now is:
Avoiding problems with ReadBuffer !

In my case I am unzipping files.
Before ReadBuffer is called, the size stream "unzip" is determined via unzip->Size.
If the size is large enough in order to read the needed information - then read, else abort.

Good solution? Save?

Edited by: Oliver Weinheimer on May 3, 2017 9:14 AM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: try catch problem with TZDecompressionStream [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 3, 2017 11:00 AM   in response to: Oliver Weinheimer in response to: Oliver Weinheimer
Oliver wrote:

After reading about asynchronous exceptions and that these ones
are not supported by the clang based compiler I replaced the last
catch ad the end of the code by:

__finally{
FILE_LOG(logERROR) << "ReadBuffer failed!";
}
return 0;

This works.

A __finally block is ALWAYS executed, whether an exception has been thrown
or not. If you use a __finally for error logging, you would need to know
WHEN to log and when NOT to log, eg:

int dim[3];
bool ok = false;
try {
    unzip->ReadBuffer(dim,3*sizeof(int));
    ok = true;
}
__finally {
    if (!ok) {
        FILE_LOG(logERROR) << "Reading of decompressed stream fails!";
    }
}


However, the documentation does say:

Instead of catching these special exceptions that Clang-enhanced compilers
cannot handle, you should do either of the following:

- Move the code that may raise an asynchronous exception to its own function
and call that function from your try block.

So try that, eg:

void ReadStreamBuffer(TStream *Stream, void *Buffer, int BufLen)
{
Stream->ReadBuffer(Buffer, BufLen);
}

...

TFileStream *input=0;
try
{
input= new TFileStream(temp_filename.c_str(), fmOpenRead);
}
catch(...)
{
input = 0;
}
if (input != 0)
{
TZDecompressionStream *unzip = 0;
try {
unzip = new TZDecompressionStream(input);
}
catch(...) {
unzip = 0;
}

if (unzip!=0)
{
int dim[3];
try{
ReadStreamBuffer(unzip, dim, 3*sizeof(int));
}
catch(...){
FILE_LOG(logERROR) << "Reading of decompressed stream fails!";
}
}

Either way, I suggest you restructure your try blocks to something more like 
this instead:
 

try
{
TFileStream *input = new TFileStream(temp_filename.c_str(), fmOpenRead);
try
{
TZDecompressionStream *unzip = new TZDecompressionStream(input);
try
{
int dim[3];
ReadStreamBuffer(unzip, dim, 3*sizeof(int));
}
__finally
{
delete unzip;
}
}
__finally
{
delete input;
}
}
catch(...)
{
FILE_LOG(logERROR) << "Reading of decompressed stream fails!";
}

Or better:
 

#include <memory>

...

try
{
std::unique_ptr<TFileStream> input(new TFileStream(temp_filename.c_str(),
fmOpenRead));
std::unique_ptr<TZDecompressionStream> unzip(new TZDecompressionStream(input.get()));

int dim[3];
ReadStreamBuffer(unzip.get(), dim, 3*sizeof(int));
}
catch(...)
{
FILE_LOG(logERROR) << "Reading of decompressed stream fails!";
}
{code}

Inside the function, code after the __finally block does not work,
just return is possible. Is that a normal behavior?

Yes, if an exception was actually thrown. A __finally block does not catch
and discard an exception like a catch() block can. The exception still continues
to propegate up the call stack after the __finally block exits.

--
Remy Lebeau (TeamB)
Oliver Weinheimer

Posts: 73
Registered: 8/20/04
Re: try catch problem with TZDecompressionStream [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 4, 2017 3:19 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thank you Remy for your reply and for the clarifications regarding __finished.

I ended up in:

1) Using an own function for the ReadBuffer code
2) Reorganization of my try blocks after you (second) advice -> one try catch, no __finally. Using std::unique_prt for input and unzip streams
3) Controll of the stream size before EVERY call of ReadBuffer function
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: try catch problem with TZDecompressionStream [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 4, 2017 10:00 AM   in response to: Oliver Weinheimer in response to: Oliver Weinheimer
Oliver wrote:

3) Controll of the stream size before EVERY call of ReadBuffer
function

You should not need to do that. The whole purpose of ReadBuffer() vs Read()
is that ReadBuffer() throws a synchronous exception (specifically, System::Classes::EReadError)
if there is an error reading the total number of requested bytes, which includes
reaching EOF. A catch() block should be able to handle that exception just
fine.

--
Remy Lebeau (TeamB)
Oliver Weinheimer

Posts: 73
Registered: 8/20/04
Re: try catch problem with TZDecompressionStream [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 8, 2017 1:37 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thanks again for your help.
As I wrote I have now a working solution for handling corrupted files.

But the conversion from asynchronous exception to synchronous exception does still not work for me.
I suspect you refer to this sentence in the help files: "Move the code that may raise an asynchronous exception to its own function and call that function from your try block." (Differences Between Clang-enhanced C++ Compilers and Previous-Generation C++ Compilers)
This does not work for me in my test with

try{
ReadStreamBuffer(unzip.get(), dim, 3*sizeof(int));
}
catch (const Exception& e){
++err_count;
FILE_LOG(logERROR) << "Can not open file.";
}

No exception is caught, program crashes. Same for catch(...) }
ReadStreamBuffer works for not corrputed files.
I am using bcc64 (Tokyo with last Hotfix), static linking.

So my solution is for this cases: "Try to prevent these exceptions from ever raising."
But catching should also work ...
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02