Programmatically Ignore printf - c++

I'm using someones library that printf's out an error message when a connection to a device is unsuccessful.
The library code prints out nothing when a connection is successful.
I periodically check (loop & sleep) to see if a device is connected but I only want to print out when it is connected.
At the moment I get something like:
Waiting for connection... (<-- My print)
Error
Error
Error
Error
Error
Connection successful (<-- My print)
What I want is:
Waiting for connection... (<-- My print)
Connection successful (<-- My print)
How can I programatically ignore a printf?
N.b. I found a similar question Programmatically Ignore Cout but that solution did not work for printf.
I am using Windows.
Can anyone help? (c/c++ novice)

Have you tried something like (before establishing connection):
FILE * myout = stdout;
stdout = fopen ("standard-output-file", "w");
To print something to output you could use then:
fprintf(myout, "format", ...);
Edit: Remember to close the file descriptor afterwards:
fclose(myout);

I was able to get this working under Linux the following way
#include <cstdio>
using namespace std;
int main() {
printf("Start\n");
freopen("/dev/null", "w", stdout);
printf("middle\n");
freopen("/dev/stdin", "w", stdout); // really stdin here!
printf("End\n");
return 0;
}
Under Windows I think there are other names for files (nul and con maybe).
However, this seems to be completely unportable, and, what's worse, this will prevent the users from redirecting your program output to a file, because I explicitly reopen /dev/stdin. There are suggestions that you can use /dev/fd/1 instead of /dev/stdin to mitigate the latter problem, but I have not tested it.
It seems that there is no reliable way, see, e.g. http://c-faq.com/stdio/undofreopen.html

I don't know the absolute solution, but you'll need to use:
freopen("conout$", "w", stderr);
Or something similar, but with "conout$" pseudo-file, which I believe is same as /dev/stdout on Linux.
You may have to use GetStdHandle, AttachConsole etc.

If you are using c++11 and above you can use a simple variadic template without much coding so this overloads printf for all cases and the original one never gets called
template <typename ...Args>
void printf(Args... ...)
{
}

Related

Is there a format processor to write my own printf-like function and keep the %d style arguments, without using sprintf?

I'm writing a serial interface for an MCU, and I want to know how one would create a printf-like function to write to the serial UART. I can write to the UART, but to save memory and stack space, and avoid temp string buffers, I would prefer to do that write directly instead of doing sprintf() to a string and then writing the string via serial. There is no kernel and no file handling, so FILE* writes like those from fprintf() won't work (but sprintf() does).
Is there something that processes formatted strings for each char, so I can print char-by-char as it parses the format string, and applies the related arguments?
We are using newlib as part of the efm32-base project.
UPDATE
I would like to note that ultimately we implemented the _write() function because thats all newlib needs to light up printf.
Standard C printf family of functions don't have a "print to a character callback" type of functionality. Most embedded platforms don't support fprintf either.
First try digging around the C runtime for your platform, it might have a built-in solution. For example, ESP-IDF has ets_install_putc1() which essentially installs a callback for printf (though its ets_printf already prints to UART0).
Failing that, there are alternative printf implementations designed specifically for embedded applications which you can adapt to your needs.
For example mpaland/printf has a function taking the character printer callback as the first argument:
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
Also see this related question: Minimal implementation of sprintf or printf.
You had said [in your top comments] that you had GNU, so fopencookie for the hooks [I've used it before with success].
Attaching to stdout may be tricky, but doable.
Note that we have: FILE *stdout; (i.e. it's [just] a pointer). So, simply setting it to the [newly] opened stream should work.
So, I think you can do, either (1):
FILE *saved_stdout = stdout;
Or (2):
fclose(stdout);
Then, (3):
FILE *fc = fopencookie(...);
setlinebuf(fc); // and whatever else ...
stdout = fc;
You can [probably] adjust the order to suit (e.g. doing fclose first, etc.)
I had looked for something analogous to freopen or fdopen to fit your situation, but I didn't find anything, so doing stdout = ...; may be the option.
This works fine if you do not have any code that tries to write to fd 1 directly (e.g. write(1,"hello\n",6);).
Even in that case, there is probably a way.
UPDATE:
Do you know if FILE*stdout is a const? If so, I might need to do something crazy like FILE **p = &stdout and then *p = fopencookie(...)
You were right to be concerned, but not for quite the reason you think. Read on ...
stdout is writable but ...
Before I posted, I checked stdio.h, and it has:
extern FILE *stdout; /* Standard output stream. */
If you think about it, stdout must be writable.
Otherwise, we could never do:
fprintf(stdout,"hello world\n");
fflush(stdout);
Also, if we did a fork, then [in the child] if we wanted to set up stdout to go to a logfile, we'd need to be able to do:
freopen("child_logfile","w",stdout);
So, no worries ...
Trust but verify ...
Did I say "no worries"? I may have been premature ;-)
There is an issue.
Here is a sample test program:
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#if 1 || DEBUG
#define dbgprt(_fmt...) \
do { \
fprintf(stderr,_fmt); \
fflush(stderr); \
} while (0)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
typedef struct {
int ioport;
} uartio_t;
char *arg = "argument";
ssize_t
my_write(void *cookie,const char *buf,size_t len)
{
uartio_t *uart = cookie;
ssize_t err;
dbgprt("my_write: ENTER ioport=%d buf=%p len=%zu\n",
uart->ioport,buf,len);
err = write(uart->ioport,buf,len);
dbgprt("my_write: EXIT err=%zd\n",err);
return err;
}
int
my_close(void *cookie)
{
uartio_t *uart = cookie;
dbgprt("my_close: ioport=%d\n",uart->ioport);
int err = close(uart->ioport);
uart->ioport = -1;
return err;
}
int
main(void)
{
cookie_io_functions_t cookie = {
.write = my_write,
.close = my_close
};
uartio_t uart;
printf("hello\n");
fflush(stdout);
uart.ioport = open("uart",O_WRONLY | O_TRUNC | O_CREAT,0644);
FILE *fc = fopencookie(&uart,"w",cookie);
FILE *saved_stdout = stdout;
stdout = fc;
printf("uart simple printf\n");
fprintf(stdout,"uart fprintf\n");
printf("uart printf with %s\n",arg);
fclose(fc);
stdout = saved_stdout;
printf("world\n");
return 0;
}
Program output:
After compiling, running with:
./uart >out 2>err
This should produce an expected result. But, we get (from head -100 out err uart):
==> out <==
hello
uart simple printf
world
==> err <==
my_write: ENTER ioport=3 buf=0xa90390 len=39
my_write: EXIT err=39
my_close: ioport=3
==> uart <==
uart fprintf
uart printf with argument
Whoa! What happened? The out file should just be:
hello
world
And, the uart file should have three lines instead of two:
uart printf
uart simple printf
uart printf with argument
But, the uart simple printf line went to out instead of [the intended] uart file.
Again, whoa!, what happened?!?!
Explanation:
The program was compiled with gcc. Recompiling with clang produces the desired results!
It turns out that gcc was trying to be too helpful. When compiling, it converted:
printf("uart simple printf\n");
Into:
puts("uart simple printf");
We see that if we disassemble the executable [or compile with -S and look at the .s file].
The puts function [apparently] bypasses stdout and uses glibc's internal version: _IO_stdout.
It appears that glibc's puts is a weak alias to _IO_puts and that uses _IO_stdout.
The _IO_* symbols are not directly accessible. They're what glibc calls "hidden" symbols--available only to glibc.so itself.
The real fix:
I discovered this after considerable hacking around. Those attempts/fixes are in an appendix below.
It turns out that glibc defines (e.g.) stdout as:
FILE *stdout = (FILE *) &_IO_2_1_stdout_;
Internally, glibc uses that internal name. So, if we change what stdout points to, it breaks that association.
In actual fact, only _IO_stdout is hidden. The versioned symbol is global but we have to know the name either from readelf output or by using some __GLIBC_* macros (i.e. a bit messy).
So, we need to modify the save/restore code to not change the value in stdout but memcpy to/from what stdout points to.
So, in a way, you were correct. It is [effectively] const [readonly].
So, for the above sample/test program, when we want to set a new stdout, we want:
FILE *fc = fopencookie(...);
FILE saved_stdout = *stdout;
*stdout = *fc;
When we want to restore the original:
*fc = *stdout;
fclose(fc);
*stdout = saved_stdout;
So, it really wasn't gcc that was the issue. The original save/restore we developed was incorrect. But, it was latent. Only when gcc called puts did the bug manifest itself.
Personal note: Aha! Now that I got this code working, it seems oddly familiar. I'm having a deja vu experience. I'm pretty sure that I've had to do the same in the past. But, it was so long ago, that I had completely forgotten about it.
Workarounds / fixes that semi-worked but are more complex:
Note: As mentioned, these workarounds are only to show what I tried before finding the simple fix above.
One workaround is to disable gcc's conversion from printf to puts.
The simplest way may be to [as mentioned] compile with clang. But, some web pages say that clang does the same thing as gcc. It does not do the puts optimization on my version of clang [for x86_64]: 7.0.1 -- YMMV
For gcc ...
A simple way is to compile with -fno-builtins. This fixes the printf->puts issue but disables [desirable] optimizations for memcpy, etc. It's also undocumented [AFAICT]
Another way is to force our own version of puts that calls fputs/fputc. We'd put that in (e.g.) puts.c and build and link against it:
#include <stdio.h>
int
puts(const char *str)
{
fputs(str,stdout);
fputc('\n',stdout);
}
When we just did: stdout = fc; we were deceiving glibc a bit [actually, glibc was deceiving us a bit] and that has now come back to haunt us.
The "clean" way would be to do freopen. But, AFAICT, there is no analogous function that works on a cookie stream. There may be one, but I haven't found it.
So, one of the "dirty" methods may be the only way. I think using the "custom" puts function method above would be the best bet.
Edit: It was after I reread the above "deceiving" sentence that I hit on the simple solution (i.e. It made me dig deeper into glibc source).
depending on your standard library implementation you need to write your own versions of fputc or _write functions.

Screwing up \n\r\t by system()

I have read and tried many solutions and nothing solved my problem.
I am generating a dll out of c++ code and want to display the printf() or the std::cout inside of a console window. For testing I just create a .exe out of the c++ code but that is not solving the problem!
I know that system("Pause") is a bad habit, but this is just an easy way to get the same problem. Instead of calling system("Pause") I'm doing a system()-call that is calling the cl.exe and is compiling a dll out of a .c file(Like: system("cl...). The generation of the dll out of the other c file is working without any problems. But after I called the system function for compiling the dll file the printf and std::out are not displaying the right text in the console window.
here is my example code that is screwing up the display of the right characters:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "Everything works fine\n";
// Calling the cl.exe by cmd...
system("Pause");
std::cout << "now its strewd up the newline is not working\n" << std::endl;
FreeConsole();
return 0;
}
Here is a picture of the output:
I tried the fflush before and after calling the system().
So here are my further thoughts:
Could I call the cl.exe by a CreateProcess and would that solve my problem?And when yes, how will I do that and to implement the environment variables out of the batch vcvars32.bat. So I want to create a dll out of a .c located both in the same folder.
Or could write a batch file that is calling the whole cl.exe and vcvars32.bat file process.
Or is there another way to display the values out of a dll instead of calling AllocConsole()?
I hope you can help me maybe I'm missing something!
So in order to try these error on my laptop (because I'm travelling today) I set up the same code at my laptop. Because I forgot to uncheck Security Development Lifecycle (SDL) checks there was an error when calling freopen("CONOUT$", "w", stdout); .Because the error message at building the code inside of visual studio 2015 was:
Severity Code Description Project File Line
Error C4996 'freopen': This function or variable may be unsafe. Consider using freopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. ConsoleApplication1 c:\users\noxious\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp 12
I searched for the function freopen_s and exact at a example of freopen_s I saw the following code Outputting Unicode to Allocated Console Issue:
freopen_s(&stream, "CONOUT$", "w+t", stdout);
I tried this one and acually my problem was solved! BUT it wasn't the freopen_s that solved the problem it was just the inside of it "w+t" so I looked it up and saw that w+ is refering to the following type of access cstdio: freopen:
"w+"
Create an empty file for reading and writing. If a file with the same name already exists its content is erased before it is opened.
So I tried a few combinations and got this resulst:
wt not working
w+t working (but the t is always standard even if you use w+ is the same as w+t
w+ working
So I think I have just to setup an empty file for reading and writing! I will looking further deep into that because I'm not quite sure what is the difference and if it is still solving the problem when using the dll instead of the exe file!
Hope this might help some other people who are trying to solve same errors! But just a "+" was delaying my work now for more than one day!
Edit 5.10.2015:
So I tested this function with the "w+" instead of "w" and it fixed my problem!Even using a dll instead of a generated exe!
It looks like the process is changing the output codepage on the console, then not changing it back when it's done. Not sure why this would happen, but if that's the cause, it should be sufficient to save and restore the codepage:
AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "Everything works fine\n";
// Calling the cl.exe by cmd...
UINT codepage = GetConsoleOutputCP();
system("Pause");
SetConsoleOutputCP(codepage);
std::cout << "Should work now." << std::endl;
FreeConsole();
return 0;
BTW, it might also be screwing up the input codepage. You can use GetConsoleCP() and SetConsoleCP() for that.

fflush on stderrr causes program to crash

I am redirecting stderr to a log file on Windows Phone Runtime:
int stdError = 0;
FILE* pLogFile = NULL;
// Redirect stderror to a logfile
if ( ! m_logFilePath.empty( ) )
{
// Get a duplicate file descriptor for stderror
// This returns -1 on failure
stdError = ::_dup( ::_fileno( stderr ) );
if ( stdError != -1 )
{
// Redirect stderror to a log file so we can capture
// ffmpeg error information
// Ignore the return value (nothing we can do if this fails)
::freopen_s( &pLogFile, m_logFilePath.c_str( ), "w", stderr );
}
}
The program intermittently crashes while calling fflush(stderr);. When I don't redirect stderr everything seems to be working fine.
It's windows so who knows?
Try std::cerr.flush(); because I can totally see windows doing their own thing again (like sockets not being like files, they like doing their own IO stuff).
Using what I just said above puts the task to their standard library, rather than assuming it's a file and such. Remember "abstraction", it makes sense flush is a method, it is a verb, and we don't care how (or in this case don't (want) to know) so let's just assume flush does what flush ought to do!
Leave a comment if this doesn't work and I shall have a think.
I don't use windows or windows phones (I am not one of the lucky 24 out there in the world :P) but I do know that there are I/O problems ("differences") on Windows, fortunately MinGW and co hide them from me :)
OR
Change your tactics, if I really wanted to side-step the problem (because it isn't your code) create a new class called my_error_stream or something, that extends std::ostream (that way you can use it like std::cerr which "is a" std::ostream).
Put a static method in that called get_error_stream() or something that returns one of two classes derived from my_error_stream, one forwards right to std::err, the other to a file.
It depends on how you like your code to look and feel, I said this way because it keeps the implementations separate, and under their own "branch" of the class hierarchy.
It doesn't really answer your question, but your code seems fine, and Windows sucks at pipes and sockets.

C++ separate command line window?

So I have a GUI program and for some reason it does not let me debug using printf().
When I use printf(), it does not go to the Visual Studio debugger for some reason.
Anyways, I wanted to make my own separate window that opens up when the GUI opens up,
and basically be able to feed information into that console and talk to it.
For example:
void talk(std::string info){
//Add the value of info to the next line in the console
}
Anyone know how to do this?
Basically create a command line and talk to it so I can see output:
CommandLine c;
c.talk("hey!");
You can create a console using AllocConsole to create a console, then write to that explicitly (there are a few methods, GetStdHandle and file write will work). You can also use OutputDebugString to write to the VS output window.
void makeConsole()
{
AllocConsole();
console = GetStdHandle(STD_OUTPUT_HANDLE);
}
void talk(std::string info)
{
WriteFile(console, info.c_str(), info.length()); // To console
OutputDebugString(info.c_str()); // To output window
}
(pseudo-code, functions may not be quite right)
Edit:
If you're writing to the console only through your talk function, this will work fine. If you're using printf/cout throughout your code, you definitely want to use Ben's method (much simpler to use repeatedly).
#peachykeen has half the solution. If you want to make printf and cout work, try this:
AllocConsole();
freopen("CONOUT$", "w", stdout);

Redirect both cout and stdout to a string in C++ for Unit Testing

I'm working on getting some legacy code under unit tests and sometimes the only way to sense an existing program behavior is from the console output.
I see lots of examples online for how to redirect stdout to another file in C++, but is there a way I can redirect it to an in-memory stream so my tests don't have to rely on the disk?
I'd like to get anything that the legacy code sends to stdout into a std::string so I can easily .find on the output.
Edit
The legacy code is so bad that it users a mixture of cout << .. and printf. Here is what I have so far:
void TestSuite::setUp(void)
{
oldStdoutBuf = std::cout.rdbuf();
std::cout.rdbuf(consoleOutput.rdbuf());
}
void TestSuite::tearDown(void)
{
std::cout.rdbuf(oldStdoutBuf);
}
The problem is that this does not capture output using printf. I would like something that gets both. Any ideas?
std::stringstream may be what you're looking for.
UPDATE
Alright, this is a bit of hack, but maybe you could do this to grab the printf output:
char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout);
setbuf(stdout, huge_string_buffer);
Note you should use "/dev/null" for linux instead of "NUL". That will rapidly start to fill up huge_string_buffer. If you want to be able to continue redirecting output after the buffer is full you'll have to call fflush(), otherwise it will throw an error. See std::setbuf for more info.
You can use freopen(..., stdout) and then dump the file into memory or a std::string.
This may be an alternative:
char bigOutBuf[8192];
char savBuf[8192];
fflush(stdout);
setvbuf(stdout,bigOutBuf,IOFBF,8192);//stdout uses your buffer
//after each operation
strncpy(savBuf,bigOutBuf,8192);//won't flush until full or fflush called
//...
//at long last finished
setbuf(stdout,NULL);//reset to unnamed buffer
This just intercepts the buffered output, so still goes to console or wherever.
Hope this helps.
Try sprintf, that's more efficient.
int i;
char str[] = "asdf";
char output[256];
sprintf(output, "asdfasdf %s %d\n", str, i);