Reading stderr

B

Bumbala

Hello,

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.
 
F

Flash Gordon

Bumbala said:
Hello,

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

As far as C is concerned stderr is a write only stream. It could, for an
extreme example, be going direct to a printer in which case the only way
to read it would be to feed the paper from the printer in to a scanner
and then OCR it. What I've said may sound daft and extreme, but it is to
make a point. The point is that in C the only way to achieve what you
want is to change the library. Annoying I'm sure, but true.
 
B

Ben Pfaff

Bumbala said:
I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

stderr is an output stream. Reading from it will, portably, have
no useful effect.
 
V

vippstar

stderr is an output stream.  Reading from it will, portably, have
no useful effect.

I remember I've been told it is undefined behavior. I don't remember
if I asked about reading streams for output or writing to streams for
input, but I've been told it's undefined behavior for fgetc/fputc with
the wrong streams, and every IO function shall behave as if it used
those two functions. Perhaps someone will be able to clarify.
 
D

Default User

Bumbala said:
Hello,

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

stderr is not a stream open for reading, only writing. About the only
way to access the information would be to use some platform-specific
methods to redirect stderr to a file, and read that file.

Are you sure this is something you need to do? What information is
being output by the library functions that isn't also provided in the
return value or errno? Can you change the library?




Brian
 
C

CBFalconer

Bumbala said:
I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the
messages in stderr in the main library. However, when I try to
read stderr as given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

I get strange characters in the buffer, not the message. However,
when I quick watch stderr, I see the message in stderr->_base
member. What am I doing wrong? Thanks.

You are not checking the returned value from fscanf. It should be
returning 0, announcing that it could not load any of the requested
items. The basic reason is that stderr is an output file, not an
input file.
 
L

Lew Pitcher

Hello,

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. [snip]
What am I doing wrong? Thanks.

As others have pointed out to you, you (at the very least) invoke "Undefined
Behaviour" when you attempt to read stderr from your code. You will get a
number of code-related suggestions here, all of which will require you to
re-architect your existing codebase so that your C++ library can read the
output of your C errorlog. I suggest to you that, in this case, code
changes of this nature would be the wrong approach to solve your logging
problem.

Your specific problem is that you want to log all the errors that the C code
writes to stderr. Your proposed solution is to read stderr in your C++
code, and have the C++ code log the errors. A much less intrusive solution
would be to have a separate process read the output that your C program
writes to stderr (through a pipe, or other IPC mechanism supported by your
operating environment), and have /that/ process perform the logging.
Chances are that such a mechanism already exists (in some form or another)
on your implementation platform, and all you have to do is use it.

In other words, I believe that you are pursueing the wrong problem, and
ignoring the right solution to your logging issue. In any case, your
solution lies outside the purvue of the comp.lang.c newsgroup.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello,

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

If it is writing the errors to stderr, you cannot (and absolutely should
not) read them back. That stream is write-only, and will nearly always
be in use to write the errors either to the terminal or (if redirected
in the shell) some file.

What you must do is modify the library. One thing it could do is set
errno or the like.

If you want to implement ugly hacks, what you could do is freopen()
stderr as "w+" or something. Of course, doing code like this gets
complicated when your own code (or other code) starts writing to stderr.
In any case, all this behaviour is most probably undefined and thus you
should use return values &c. to check for errors.

In your code, I would guess that the return code from fscanf() is EOF,
and errno is set to EBADF. Thus, the garbage you see is just what was in
your uninitialized heap memory before.

- --
- --Falcon Darkstar Kirtaran
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJc56JAAoJEKmxP9YxEE4rU0QP/jPmRUBULycyZbdHuycHbhZd
fvgj7OkYpz18UEL9cB9c4lj3eB5L8X75I9f4cKRSrt9ce1igkHFvsRMfbcxcvtpc
0DxET6680GUUCZTuq5aGibQQhvG2MLz4wlw/9u622xjik5cwsO448JGfI1jVFL5h
NFa1iAfDTXIZVePSt3B6o3RPqN/lWdz+S4ttBbJQ383dQ7iY2454CtYvsYogglLL
XGdw2r3oWvIqpMtdGqtJEu5GRbORkuw6RbUJz4PSf62WGkVRaC/LrchT008K5C1/
Oe6JeKxapuxkZoaE66reaudiLn3vfUG3xvgIKrHfsbSObXIErf9lPO7PADYDAT4R
XbrgkgCLoAyDFFACs3g/9jaA67khkOzj3ipG+kqSRSNAv6QXj5N/8qx520/4t6ec
MnTdyXqL7j/U5R9AiACwy71kW76mrKWG5NiIeV5/zUj0kmvG1F4W1gb0UIod0pjf
7PUCtSXT9Z492HjBokN9jYp1K994ZXVcL13JNQRw/fFFDdII9rFDH5k31B/X10Af
6rUW5MS9ptkK4JH1Uk8BlCI4HKS+Z7KU4RhoXBfWU+4HSSo6Btyga6zpDLIcm/Nr
Vy5lrAGJvmV76l547mOx6Jw67e2TrnbjTugjWMidGmR6/I4GQ+Y6K3Z2PyrdRbx0
g64PJZKnFz/IcdALkc0u
=A2gj
-----END PGP SIGNATURE-----
 
A

Antoninus Twink

The static library performs some operations and outputs to "stderr" if
an error is occured. I want to log the messages in stderr in the main
library. However, when I try to read stderr as given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

First up, unless you're *sure* that the messages produced by the library
won't exceed 4096 bytes, an unbounded string scan like this could lead
to a buffer overflow.
I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

As people have said, this is difficult to do portably.

One solution on POSIX-like systems would be to use an anonymous pipe to
temporarily replace stderr's file descriptor. Here is some example code
to give you the idea:

#include <stdio.h>
#include <unistd.h>

void some_library_function(void)
{
fputs("hello!\n", stderr);
}

int main(void)
{
int stderr_backup, pipefd[2];
char buf[4096];
if(pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
if((stderr_backup = dup(STDERR_FILENO)) == -1) {
perror("dup");
return 1;
}
if(dup2(pipefd[1], STDERR_FILENO) == -1) {
perror("dup2");
return 1;
}
some_library_function();
if(read(pipefd[0], buf, sizeof(buf)) == -1) {
perror("read");
return 1;
}
buf[sizeof(buf)-1]='\0';
printf("read from stderr: %s", buf);
close(pipefd[0]);
close(pipefd[1]);
if(dup2(stderr_backup, STDERR_FILENO) == -1) {
perror("dup2");
return 1;
}
puts("== original stderr now restored ==");
some_library_function();
return 0;
}
 
A

Antoninus Twink

The static library performs some operations and outputs to "stderr" if
an error is occured. I want to log the messages in stderr in the main
library. However, when I try to read stderr as given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

First up, unless you're *sure* that the messages produced by the library
won't exceed 4096 bytes, an unbounded string scan like this could lead
to a buffer overflow.
I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

As people have said, this is difficult to do portably.

One solution on POSIX-like systems would be to use an anonymous pipe to
temporarily replace stderr's file descriptor. Here is some example code
to give you the idea:

#include <stdio.h>
#include <unistd.h>

void some_library_function(void)
{
fputs("hello!\n", stderr);
}

int main(void)
{
int stderr_backup, pipefd[2];
char buf[4096];
if(pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
if((stderr_backup = dup(STDERR_FILENO)) == -1) {
perror("dup");
return 1;
}
if(dup2(pipefd[1], STDERR_FILENO) == -1) {
perror("dup2");
return 1;
}
some_library_function();
if(read(pipefd[0], buf, sizeof(buf)) == -1) {
perror("read");
return 1;
}
buf[sizeof(buf)-1]='\0';
printf("read from stderr: %s", buf);
close(pipefd[0]);
close(pipefd[1]);
if(dup2(stderr_backup, STDERR_FILENO) == -1) {
perror("dup2");
return 1;
}
puts("== original stderr now restored ==");
some_library_function();
return 0;
}
 
A

Antoninus Twink

The static library performs some operations and outputs to "stderr" if
an error is occured. I want to log the messages in stderr in the main
library. However, when I try to read stderr as given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

First up, unless you're *sure* that the messages produced by the library
won't exceed 4096 bytes, an unbounded string scan like this could lead
to a buffer overflow.
I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

As people have said, this is difficult to do portably.

One solution on POSIX-like systems would be to use an anonymous pipe to
temporarily replace stderr's file descriptor. Here is some example code
to give you the idea:

#include <stdio.h>
#include <unistd.h>

void some_library_function(void)
{
fputs("hello!\n", stderr);
}

int main(void)
{
int stderr_backup, pipefd[2];
char buf[4096];
if(pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
if((stderr_backup = dup(STDERR_FILENO)) == -1) {
perror("dup");
return 1;
}
if(dup2(pipefd[1], STDERR_FILENO) == -1) {
perror("dup2");
return 1;
}
some_library_function();
if(read(pipefd[0], buf, sizeof(buf)) == -1) {
perror("read");
return 1;
}
buf[sizeof(buf)-1]='\0';
printf("read from stderr: %s", buf);
close(pipefd[0]);
close(pipefd[1]);
if(dup2(stderr_backup, STDERR_FILENO) == -1) {
perror("dup2");
return 1;
}
puts("== original stderr now restored ==");
some_library_function();
return 0;
}
 
K

Kenny McCormack

Hello,

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

I get strange characters in the buffer, not the message. However, when
I quick watch stderr, I see the message in stderr->_base member.

What am I doing wrong? Thanks.

Well, for starters, you're asking in a group full of useless twats, who
will give you a whole big song-and-dance about how your post is:

Off topic. Not portable. Cant discuss it here. Blah, blah, blah.

Which all boils down to "We know the answer, but we're not gonna tell ya
- nanny, nanny, boo boo". Note that it is not the case that your
question actually *is* off-topic; it's just the jerks here, for reasons
that are pretty much rooted in religion (i.e., fantasy), refuse to talk
about it. So, their advice (ask somewhere else) is actually correct,
but not for the reasons that they state. There are, of course,
exceptions to this rule (that no one here will help you), but you will
quickly find that those who do deign to actually help, are quickly
branded as "trolls". I'm one of them. There are others.

Having said all that, let me address your issue. Yes, your problem is
common, well-defined, and solvable. I had to do just that some time
ago; I had a library that was generating output on both stdout and
stderr, and I wanted to capture that output, without going the kludge
route of letting it write out to a file and reading the file back in. (*)

Now, I won't go into the full details (it is much more fun to work it
out on your own), but the basic method is to use some variation of the
setbuf() call to create a large buffer (large enough to contain as much
as output as you ever expect to get - i.e., so that it never actually
gets written out) for the stream(s) in question. Then, after the
library routine returns, you can poke around in the buffer and get out
what you need. Yes, this requires poking around inside the guts of the
"FILE *" structure. Again, despite what the useless twats here tell you,
you won't hurt yourself by doing this. Nor will you go blind...

(*) Note that some of the useless twats here will (and in fact, already
have) stated that this is the only "portable" way to do it. This
obsession with "the only portable way" is one of the many attributes
that marks them as useless twats.
 
B

Ben Pfaff

CBFalconer said:
You are not checking the returned value from fscanf. It should be
returning 0, announcing that it could not load any of the requested
items. The basic reason is that stderr is an output file, not an
input file.

I would expect it to return EOF, announcing that an input failure
occurred before any conversion. (If such an operation is not
actually undefined, but I couldn't find anything that says it
is.)
 
B

Ben Pfaff

stderr is an output stream.  Reading from it will, portably, have
no useful effect.

I remember I've been told it is undefined behavior. [...]

That would not surprise me, but in a quick scan through C99 I
couldn't find anything that says so. Anyone have a cite?
 
B

Ben Pfaff

I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

Having said all that, let me address your issue. Yes, your problem is
common, well-defined, and solvable. [...]

Common? Really? This is the first time I remember this question
being asked here.
 
B

Bumbala

Thank you all for the remarks and suggestions :)

Here is another option: The static library accepts the out and err
streams as paramaters like:

exitcode = SomeFunction(some parameters... , FILE *sout, FILE *serr);

So I think, it is possible to supply other than stdout and stderr. For
example, fopen("somefile", "w") and this solves my problem. In order
not to create-delete temp files, is it possible to pass a memory
stream?

Thanks.
 
C

CBFalconer

Ben said:
I would expect it to return EOF, announcing that an input failure
occurred before any conversion. (If such an operation is not
actually undefined, but I couldn't find anything that says it
is.)

I didn't try to check. At least we agree it won't return 1.
 
B

Ben Bacarisse

Bumbala said:
Thank you all for the remarks and suggestions :)

Here is another option: The static library accepts the out and err
streams as paramaters like:

exitcode = SomeFunction(some parameters... , FILE *sout, FILE *serr);

So I think, it is possible to supply other than stdout and stderr. For
example, fopen("somefile", "w") and this solves my problem. In order
not to create-delete temp files, is it possible to pass a memory
stream?

Not in standard C, but most systems will provide some way to output to
memory. You will need to study your C implementation's
documentation to see if there is one.
 
B

Ben Bacarisse

Antoninus Twink said:
One solution on POSIX-like systems would be to use an anonymous pipe to
temporarily replace stderr's file descriptor. Here is some example code
to give you the idea:

<snip code>

For a while you stuck to complaining, but you've returned to
misleading posters with off-topic but incorrect advice.

To the OP: Antoninus Twink's purpose is to disrupt this group by
getting people to discuss "solutions" that are off topic. If you want
to know what is wrong with it, post it in comp.unix.programmer and ask
for a review of this solution. Of course, I may be the one who is
wrong, but this is not the place to find out.
 
R

Richard

Ben Pfaff said:
I have C++ library with /clr support which links a static library
written in "C". The static library performs some operations and
outputs to "stderr" if an error is occured. I want to log the messages
in stderr in the main library. However, when I try to read stderr as
given below:

char buffer[4096];
fscanf(stderr, "%s", buffer);

Having said all that, let me address your issue. Yes, your problem is
common, well-defined, and solvable. [...]

Common? Really? This is the first time I remember this question
being asked here.

In fairness, common problems are not all posted here.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top