Comments (6)
Hi Aous,
I have successfully tested the 0.14.0 release and have confirmed that it resolves this issue. Many thanks.
Best Regards,
John Fralinger
from openjph.
Hi Fralinjh,
Thank you for looking at my code.
Before any modifications, I can see an error in message_error::operator()
function.
It is currently,
if (error_stream == NULL)
return;
fprintf(error_stream, "ojph error 0x%08X at %s:%d: ",
error_code, file_name, line_num);
va_list args;
va_start(args, fmt);
vfprintf(error_stream, fmt, args);
fprintf(error_stream, "\n");
va_end(args);
throw std::runtime_error("ojph error");
but I think it should be -- not super sure, and need to test.
if (error_stream != NULL)
fprintf(error_stream, "ojph error 0x%08X at %s:%d: ",
error_code, file_name, line_num);
va_list args;
va_start(args, fmt);
if (error_stream != NULL) {
vfprintf(error_stream, fmt, args);
fprintf(error_stream, "\n");
}
va_end(args);
throw std::runtime_error("ojph error");
I am still learning, and this runtime_error is not an easy part.
Going back to your suggestion -- thank you.
- Isn't the currently available printing to std_err enough? Is this a necessary feature, or a good to have?
- How will the buffer
char *buf0
be freed? I think it should be freed, otherwise an implementer can catch the exception and retry to use the library, causing a memory leak. - Throughout the code I tried to minimize, almost eliminate all new/delete or malloc/free from the code -- the code might under large revamp in a couple of months time.
Long discussion:
I think there is no clean solution, but if we really want this, then I can see a couple of options.
- Copy buf0 contents to std::string, and then free it before throwing the exception -- too many allocations/de-allocations.
- Create a class to hold the buffer with a destructor, freeing the memory -- not sure if this is a good idea.
Please let me know what you think.
Kind regards,
Aous.
PS:
Notes on https://en.cppreference.com/w/cpp/error/runtime_error says
Because copying std::runtime_error is not permitted to throw exceptions, this message is typically stored internally as a separately-allocated reference-counted string.
It looks like the message is internally stored as std::string.
from openjph.
Hi Aous,
First let me apologize because the diffs I previously sent were applied to OpenJPH release 0.10.5. I should have referenced the trunk or specifically stated the OpenJPH version 0.10.5 when I opened the issue. I also agree that it is good to check error_stream for null and that the corrections you propose make sense. The use of varargs from C does add some alloc/dealloc annoyances that I tried to avoid but was unsuccessful even after searching the internet.
Like you said, error processing is always more difficult than it should be. Presenting errors and warnings etc. to the user via GUI applications seldom works using log files, then alone multiple log files that lack context synchronization. We prefer Error, Warning and Info callbacks as was done in OpenJPEG if that is possible. The info/warning/error strings in the callbacks can be logged with context, presented in a dialog or even just ignored.
Until then getting error diagnostics to the user via the code below is helpful.
////////////////////////////////////////////////////////////////////////////
void message_error::operator()(int error_code, const char* file_name,
int line_num, const char *fmt, ...)
{
size_t sz = snprintf(nullptr, 0, "ojph error 0x%08X at %s:%d: ", error_code, file_name, line_num);
size_t bufsize = sz + 1;
char *buf0 = static_cast<char*>(malloc(bufsize));
snprintf(buf0, bufsize,"ojph error 0x%08X at %s:%d: ", error_code, file_name, line_num);
std::string str0 = buf0;
free(buf0);
if (error_stream)
fprintf(error_stream, str0.c_str());
va_list args;
va_start(args, fmt);
sz = vsnprintf(nullptr, 0, fmt, args);
bufsize = sz + 1;
char *buf = static_cast<char*>(malloc(bufsize));
assert(buf);
vsnprintf(buf, bufsize, fmt, args);
if (error_stream)
vfprintf(error_stream, fmt, args);
if (error_stream)
fprintf(error_stream, "\n");
va_end(args);
std::string str = buf;
free(buf);
throw std::runtime_error(str0 + str);
}
}
Once again,
Thank you for your contributions,
The code is useful and impressively fast.
Best Regards,
John Fralinger
from openjph.
Hi John,
Thank you for spending the time looking into this.
I guess this is the best currently available option.
Leave it with me; I will add a variation of this in the next version.
Kind regards,
Aous.
from openjph.
Hi John,
I am sorry I changed my mind. However, now you have a way to whatever you want on your side.
After reading the code, trying to remember what I did, I realized that there was, by design, a method that allows the end user to basically do whatever they want, but the code to achieve that was buggy. This has been fixed now.
So to support your use case, derive a new class from ojph::message_error, and define your own operator(), which should throw an exception before exiting. Then, tell the library to use this class by calling configure_error().
Here is a version of the code that you can use, part of which was to be used before changing my mind.
////////////////////////////////////////////////////////////////////////////
class my_error : public ojph::message_error
{
public:
void operator() (int warn_code, const char* file_name,
int line_num, const char *fmt, ...) override
{
int t = snprintf(NULL, 0, "ojph error 0x%08X at %s:%d: ",
error_code, file_name, line_num);
int total_bytes = t;
int max_bytes = t;
va_list args, args_copy;
va_start(args, fmt);
va_copy(args_copy, args); // create a copy of args.
t = vsnprintf(NULL, 0, fmt, args);
total_bytes += t;
max_bytes = ojph_max(max_bytes, t);
t = snprintf(NULL, 0, "\n");
total_bytes += t;
max_bytes = ojph_max(max_bytes, t);
va_end(args);
++max_bytes; // one extra
++total_bytes;
constexpr int max_store = 256;
char tmp[max_store]; // on the stack, hopefully enough
char *p = tmp;
if (max_bytes > max_store) // if more is needed then malloc
p = (char*)malloc(max_bytes);
std::string s(total_bytes, ' '); // create an string large enough
snprintf(p, max_bytes, "ojph error 0x%08X at %s:%d: ",
error_code, file_name, line_num);
s = p;
va_start(args_copy, fmt);
vsnprintf(p, max_bytes, fmt, args_copy);
va_end(args_copy);
s += p;
s += '\n';
if (p != tmp)
free(p);
if (error_stream != NULL)
fprintf(error_stream, "%s\n", s.c_str());
throw std::runtime_error(s);
}
};
Then you instantiate the object and call configure_error().
my_error e;
ojph::configure_error(&e);
Then any error will call your code.
Hope this helps.
Kind regards,
Aous.
from openjph.
Great to hear this.
Thank you for letting me know.
I am closing this issue.
Kind regards,
Aous.
from openjph.
Related Issues (20)
- typo in CMakeLists.txt HOT 1
- ojph_compress support for uppercase file extensions HOT 1
- signed 16bit negative values mismatch in interoperablity test between openjph and kakadu HOT 2
- Incorrect COM marker length HOT 1
- openjph decompression fails HOT 2
- Question : what format to be used to decompress the color HTJ2K compressed imaging data HOT 6
- Build should not fail if SIMD optimizations are enabled and your CPU doesn't support them HOT 2
- Feature: Support ROI based rendering HOT 1
- Sample JPH images, please HOT 5
- Unable to build using MinGW HOT 3
- Apple silicon build error HOT 5
- Support decode/expand a j2c file with just tilepart bytes HOT 2
- Tests fails to pass in version 0.10.4 HOT 2
- Specifying non-standard binary and library directories complicates integration in other projects HOT 1
- Feature Request: Add support for vcpkg HOT 1
- Encode 115x25的YUV444 picture,There is serious distortion. HOT 4
- Recommend adding a logging level to ojph_wrapper.cpp HOT 2
- -fexceptions is missing when configuring the wasm build HOT 2
- -resilient documentation is vague in ojph_expand HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from openjph.