I've got a Java application that calls a DLL written in C++ via JNI, this DLL then dynamically loads another DLL. Somehow messages written to cerr in C++ turn up in some cases on some computers in the Stdout-Stream of the Java part. There is no explicit redirection of any of the standard streams (cerr, cout, Stdout, Sterr etc.) in either the C++ part nor in the Java part.
How can this happen? How can I ensure that the cerr-stream of the C++ layer ends up in the Stderr-stream of the Java layer?
The JVM is in all cases the same,
JRE version: 6.0_27-b07, Java VM: Java HotSpot(TM) Client VM (20.2-b06 mixed mode windows-x86 )
cout is an object of the stdout stream, while cerr is an object of the stderr stream. stdout and stderr are different streams, even though they both refer to console output by default.
The “c” in cerr refers to “character” and 'err' means “error”, Hence cerr means “character error”. It is always a good practice to use cerr to display errors.
std::cerr is an object of class ostream that represents the standard error stream oriented to narrow characters (of type char). It corresponds to the C stream stderr. The standard error stream is a destination of characters determined by the environment.
cerr with Insertion Operator The "c" in cerr refers to "character" and "err" means "error". Hence cerr means "character error". The cerr object is used along with the insertion operator << in order to display error messages.
To answer your question directly, std::cerr can only show up in System.out if they share the same descriptor.
If it genuinely happens on some computers and not others, I'd suspect differences in the Java implementations of default System.out and System.err. You did not indicate identical Java installations, just different computers. Java makes no guarantee about its default output stream implementations.
Now, because the buffering and file descriptors on each side are uncoordinated with each other, only two possibilities exist:
1) You have access to the DLL source and can change all I/O to utilize your passed in System.out/err Java streams.
2) You don't. At that point, even if you apparently succeed through cooperative flushing, you cannot prove correctness beyond experimental evidence that your hack appears to work. There is a good chance that experimentation will not uncover corner cases where buffers are exactly full, empty, or when they share the same file descriptor.
Hopefully you are able to choose #1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With