Why does printf not print after running the png_read_png function? - c

Platform=Win10x64 Compiler=GCC Lang=C Lib=libpng16.dll
I'm trying to use the libpng library, but printf outputs nothing after this line:
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
Full code:
#include <stdio.h>
#include <png.h>
int main(int argc, char* argv[])
{
printf("starting...\n");
FILE *fp = fopen("test.png", "rb");
if (!fp) {
printf("error #%d\n", 1);
}
// Read the PNG header
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
printf("error #%d\n", 2);
}
// create stuct for png info/meta data
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
printf("error #%d\n", 3);
}
if (setjmp(png_jmpbuf(png_ptr))) {
printf("error #%d\n", 4);
}
png_init_io(png_ptr, fp);
// Read the PNG image data
printf("before printf dies\n");
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
printf("this will not print after png_read_png is ran\n");
fflush(stdout);
/* it won't print regardless if the below cleanup code is commented out or not */
// Get the image dimensions and bit depth
png_uint_32 width, height;
int bit_depth, color_type;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
// Allocate memory for the image data
png_bytep *row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep));
for (png_uint_32 i = 0; i < height; i++)
{
row_pointers[i] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
}
// Read the image data into memory
png_read_image(png_ptr, row_pointers);
// Clean up
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
// Free the memory allocated for the image data
for (png_uint_32 i = 0; i < height; i++)
{
png_free(png_ptr, row_pointers[i]);
}
png_free(png_ptr, row_pointers);
/**/
fclose(fp);
return 0;
}
It will output this:
starting...
before printf dies
Sorry for the newb question. But I can't find any information on this. Just a bunch of posts saying to end printf with a newline, but I am doing that. Thank you in advance for any help!

The explanation for why your code appears to lock up and not progress is because you are misunderstanding what setjmp() returns. You seem to think it returns 0 for success, and !0 for an "error".
This not correct. It returns 0 for when you actually call setjmp(), and !0 for when some other code calls longjmp() and returns you to there.
png_read_image() seems to be (for some reason) calling jongjmp() to signal an error. So your code enters an infinite loop.
All of your tests for errors should not just log the error then continue with the program. They should exit() or return.
There is obviously some other problem (why png_read_image() is failing), but this is the explanation for your current problem (code locks up).

After much investigation, it appears that png_read_png was encountering an error that it could not report (even with setjmp and custom error trapping). The reason for this appears to be an incompatibility between the source code and the binary that was packaged with the source. So, there is currently no way to program with libpng with C on Windows 10 without compiling the libpng from src and creating your own binary, unless you can find a 3rd party who offers a Windows x64 binary with compatible source code.
To recap on why printf is not printing:
png_read_png encounters an unexpected situation due to unknown src/binary mismatch
png_read_png is unable to call a custom error handler and jumps to the setjpm point before png_read_png is called
png_read_png is called again and the cycle continues
Windows must somehow detect an endless loop and the program quietly exits, looking as if it finished without printing, but never actually reaching the lower printf statements
???
Profit

Related

"\\.\\PhysicalDrive1" is not a core dump: file format not recognized

I have been working on a fantasy console type project. I decided to zero a flash drive I had laying around and use it as the ROM input to the fantasy console. While trying to write code to read bytes directly from the drive (rather than from a file on the drive) I have found a peculiar bug.
Trying to open the drive via CreateFile and ReadFile with the file path \\.\\PhysicalDrive1 results in the error ""\\.\\PhysicalDrive1" is not a core dump: file format not recognized"
I have tried changing input options and I have tried alternate file paths, but anything I try results in the drive either not being found or the error shown above. Information on this issue is very scarse from my research, and what little info I have found is specific to Linux, and involves very different situations.
Here is my code (not the cleanest but it should work):
#include <windows.h>
#include <fileapi.h>
#include <stdio.h>
#include <stdint.h>
int main(int argc, char *argv[]) {
printf("Opening %s\n", argv[1]);
HANDLE romf = CreateFile((LPCSTR)argv[1],
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (romf == INVALID_HANDLE_VALUE) {
printf("File %s not found\n", argv[1]);
return -1;
}
uint8_t rom[4] = { 0 };
LPDWORD read = 0;
int res = ReadFile(romf, rom, 4, read, NULL);
if (res == 0) {
printf("Error reading file (%d)\n", argv[1], GetLastError());
CloseHandle(romf);
return -1;
}
printf("Read $%x bytes\n", read);
printf("%02x %02x %02x %02x\n", rom[0], rom[1], rom[2], rom[3]);
CloseHandle(romf);
return 0;
}
I have used gdb to debug the code and to get the error message.
Nothing in the code you have shown produces the error message that you have claimed. That error message is a debugger message, not a compiler error, or a runtime system error. This issue has nothing to do with the code you have shown, and everything to do with how you are using the debugger.
Per the gdb documentation:
You can also start with both an executable program and a core file specified:
gdb program core
In comments, you state that you are running gdb ./bin/clt \\.\\PhysicalDrive1, which means you are calling gdb with \\.\\PhysicalDrive1 in the core parameter, but that path does not point to a valid core dump file, hence the error. You are expecting gdb to pass \\.\\PhysicalDrive1 as a command-line parameter to your program, but that is not what it is actually doing. To do that, use the --args parameter (see How do I run a program with commandline arguments using GDB within a Bash script?), eg:
gdb --args ./bin/clt \\.\PhysicalDrive1
That said, there are a number of bugs in your code.
you are not checking if argc > 1 is true before accessing argv[1].
the LPCSTR cast in the lpFileName parameter of CreateFile() is not needed and should be removed. argv[1] is a char* and you are casting it to const char* (which CreateFile() wants, if you are compiling a MBCS build and not a UNICODE build). The compiler can do that cast implicitly for you.
you are passing a NULL pointer to the lpNumberOfBytesRead parameter of ReadFile(). Per the documentation:
[out, optional] lpNumberOfBytesRead
A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
You are not performing an asynchronous read, so you must provide a pointer to an actual DWORD variable instead:
DWORD read = 0;
int res = ReadFile(romf, rom, 4, &read, NULL);
your error message when ReadFile() fails is being formatted incorrectly. You forgot to include a %s placeholder for argv[1], so you are passing argv[1] (a char*) to the %d placeholder, which expects an int, and you are not passing the value of GetLastError() to any placeholder at all. You need to fix your format string, eg:
printf("Error reading file %s (%d)\n", argv[1], GetLastError());

Segmentation fault when trying to create multiple threads for file IO:

I am facing a segmentation fault when I run the following program . I
am trying to make a multithreading program which performs 100 times :
Open the file.
Read the last line of the file (each line contains a number).
Add 3 to the number.
Append the new number at the end of the file.
Close the file.
The number of threads is specified by the user.
When I create 2 threads, this code runs correctly,
but when I try to create 1 or a number different from 2,
it shows segmentation fault.
I am using a semaphore for synchronization among threads.
Do you have any idea why this happens ?
Part of main:
for(i=0;i<NumberOfThreads;i++) {
if (pthread_create( pid[i], NULL, subthread, NULL ) != 0) {
fprintf(stderr, "pthread_create failed with i = %d. errno = %d, %s\n",i, errno, strerror(errno));
break;
}
}
for(i=0;i<NumberOfThreads;i++) {
pthread_join(*pid[i], NULL);
}
return 0;
}
void *subthread(void) {
int i ;
int temp ;
char ch;
int offset =0 ;
FILE * fd1 ;
FILE * fd2 ;
for(i=0 ;i<100;i++) {
sem_wait(&sem1);
fd1 = fopen (NameOfFile,"r");
fseek (fd1,-2,SEEK_END);
offset=-2;
while((ch=getc(fd1)) !='\n')
{
offset=offset-1;
fseek (fd1,offset,SEEK_END);
}
fscanf(fd1,"%d",&temp);
fclose(fd1);
fd2 = fopen (NameOfFile,"a");
temp=temp+3;
fprintf(fd2,"\n%d",temp);
printf("%d\n",temp);
fclose(fd2);
sem_post(&sem1);
}
pthread_exit(0);
}
This is just a part of the code.
When I run the code and give 1 thread as an input, it shows an segmentation fault. For 2 threads the execution is correct.
For more than 2 threads it shows again segmentation fault
When I try to debug, to see what is causing the segmentation fault, the log says that the function PTHREAD_CREATE causes it.
For pthread_create() the pointer passed as first argument must point to a valid location where pthread_create() writes thre thread id.
But as you have said in a comment, pid is defined as
pthread_t * pid[NumberOfThreads+1];
which is an array of pointers that do not point to a valid location initially. They might be NULL or undetermined depending on how the array is defined.
I would suggest you change the definition to
pthread_t pid[NumberOfThreads+1];
and call pthread_create(pid+i,....) or pthread_create(&pid[i],...); and use pid[i] instead of *pid[i] for other pthread_...() calls

Redirect printf to fopencookie

On Linux (Raspbian on a Raspberry Pi) I would like to make it so that anything my C application prints using printf is sent back to me in a callback.
(No, I'm not talking about shell redirection with > some_file.txt. I'm talking about a C program making the decision by itself to send stdout (and therefore printf) to a callback within that same program.)
(Yes, I really do want to do this. I'm making a full-screen program using OpenGL and want to present any printf'd text to the user within that program, using my own rendering code. Replacing all printf calls with something else is not feasible.)
I feel like this should be easy. There are variations of this question on StackOverflow already, but none that I could find are exactly the same.
I can use fopencookie to get a FILE* that ends up calling my callback. So far, so good. The challenge is to get stdout and printf to go there.
I can't use freopen because it takes a string path. The FILE* I want to redirect to is not a file on the filesystem but rather just exists at runtime.
I can't use dup2 because the FILE* from fopencookie does not have a file descriptor (fileno returns -1).
The glibc documentation suggests that I can simply reassign stdout to my new FILE*: "stdin, stdout, and stderr are normal variables which you can set just like any others.". This does almost work. Anything printed with fprintf (stdout, "whatever") does go to my callback, and so does any printf that has any format specifiers. However, any call to printf with a string with no format specifiers at all still goes to the "original" stdout.
How can I achieve what I'm trying to do?
PS: I don't care about portability. This will only ever run on my current environment.
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <stdarg.h>
#include <alloca.h>
#include <string.h>
static ssize_t my_write_func (void * cookie, const char * buf, size_t size)
{
fprintf (stderr, "my_write_func received %d bytes\n", size);
char * copy = (char*) alloca (size + 1);
assert (copy);
copy[size] = 0;
strncpy (copy, buf, size);
fprintf (stderr, "Text is: \"%s\"\n", copy);
fflush (stderr);
return size;
}
static FILE * create_opencookie ()
{
cookie_io_functions_t funcs;
memset (&funcs, 0, sizeof (funcs));
funcs.write = my_write_func;
FILE * f = fopencookie (NULL, "w", funcs);
assert (f);
return f;
}
int main (int argc, char ** argv)
{
FILE * f = create_opencookie ();
fclose (stdout);
stdout = f;
// These two DO go to my callback:
fprintf (stdout, "This is a long string, fprintf'd to stdout\n");
printf ("Hello world, this is a printf with a digit: %d\n", 123);
// This does not go to my callback.
// If I omit the fclose above then it gets printed to the console.
printf ("Hello world, this is plain printf.\n");
fflush (NULL);
return 0;
}
This appears to be a bug in GLIBC.
The reason that printf("simple string") works differently from printf("foo %d", 123) is that GCC transforms the former into a puts, with the notion that they are equivalent.
As far as I can tell, they should be equivalent. This man page states that puts outputs to stdout, just like printf does.
However, in GLIBC printf outputs to stdout here, but puts outputs to _IO_stdout here, and these are not equivalent. This has already been reported as a glibc bug (upstream bug).
To work around this bug, you could build with -fno-builtin-printf flag. That prevents GCC from transforming printf into puts, and on my system produces:
$ ./a.out
my_write_func received 126 bytes
Text is: "This is a long string, fprintf'd to stdout
Hello world, this is a printf with a digit: 123
Hello world, this is plain printf.
"
This workaround is of course incomplete: if you call puts directly, or link in object files that call printf("simple string") and were not compiled with -fno-builtin-printf (perhaps from 3rd-party library), then you'll still have a problem.
Unfortunately you can't assign to _IO_stdout (which is a macro). The only other thing you could do (that I can think of) is link in your own puts, which just returns printf("%s", arg). That should work if you are linking against libc.so.6, but may cause trouble if you link against libc.a.
You can redirect to a pipe instead and process the written data in a separate thread.
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
// this is the original program which you can't change
void print(void) {
printf("Hello, %d\n", 123);
puts("world");
printf("xyz");
}
int p[2];
void *render(void *arg) {
int nread;
char buf[1];
while((nread = read(p[0], buf, sizeof buf)) > 0) {
// process the written data, in this case - make it uppercase and write to stderr
for(int i = 0; i < nread; i++)
buf[i] = toupper(buf[i]);
write(2, buf, nread);
}
return NULL;
}
int main() {
setvbuf(stdout, NULL, _IONBF, 0);
pipe(p);
dup2(p[1], 1);
close(p[1]);
pthread_t t;
pthread_create(&t, NULL, render, NULL);
print();
close(1);
pthread_join(t, NULL);
}
On debian stretch putting:
setvbuf (f, NULL, _IOLBF, 0); // line buffered
after the create_opencookie call worked.

Unable to create process inside a namedpipe in Windows 7

I have the following c code which I took from the first answer to this question, I am compiling it with C89 in VS2008 so I made a couple of changes for the code to work it properly, it compiles just fine, but it's not able to create process after creating the namedpipe successfully (CreateProcessA is not working) returning always error 2 and printing the message in the panic function.
The program that I am trying to run in the CreateProcessA can be downloaded here, and I normally run it and use it as follows:
> C:\qhichwa>cmd.exe /c "C:\qhichwa\flookup.exe -bx C:\qhichwa\qhichwa.fst"
wasi <user writes wasi>
wasi <program responds printing wasi>
hola <user writes hola>
+ ? <program responds printing + ?>
<pres ctrl + c to terminate program>
> C:\qhichwa>
The lines between < comments > are just comments.
what are the corrections needed in order to to create the named pipe successfully?
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
// name of our glorious pipe
#define PIPE_NAME L"\\\\.\\pipe\\whatever" // bloody unicode string
// exit on fatal error
void panic(const char * msg)
{
int err = GetLastError();
fprintf(stderr, "***PANIC*** %s\n", msg);
printf("In the child thread: Last Error is %lu\n", err);
exit(-1);
}
// father process
void father(const char * own_name) // name of our own executable to launch a copy of ourselve
{
printf("Father process starting\n");
// create a monodirectional father->child named pipe
HANDLE pipe = CreateNamedPipe(
PIPE_NAME, // name of the pipe
PIPE_ACCESS_OUTBOUND, // send only
PIPE_TYPE_BYTE, // send data as a byte stream
1, // only one instance
0, 0, 0, NULL); // default junk
if (pipe == INVALID_HANDLE_VALUE) panic("could not create pipe 1");
// spawn child process
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessA( // using ASCII variant to be compatible with argv
"cmd.exe", // executable name (ourself)
"/c \"C:\\qhichwa\\flookup.exe -bx C:\\qhichwa\\qhichwa.fst\"", // command line. This will be seen as argv[0]
NULL, NULL, FALSE, // default junk
CREATE_NEW_CONSOLE, // launch in another console window
NULL, NULL, // more junk
&si, &pi)) // final useless junk
panic("could not create child process 2");
}
// connect to child process
BOOL result = ConnectNamedPipe(pipe, NULL);
if (!result) panic("could not connect to child process");
// talk to child
for (;;)
{
// read an input line
char line[100];
printf("Say something >");
if (fgets(line, sizeof(line), stdin) == NULL)
panic("could not read from standard input");
// exit on an empty line
if (!strcmp(line, "\n")) break;
// send the line to the child
DWORD written = 0;
if (!WriteFile(
pipe,
line, // sent data
strlen(line), // data length
&written, // bytes actually written
NULL))
panic("could not write to pipe");
}
// close the pipe
CloseHandle(pipe);
}
void child(void)
{
printf("Child process starting\n");
// retrieve communication pipe
HANDLE pipe = CreateFile(
PIPE_NAME, // name of the pipe
GENERIC_READ, // read ONLY access (or else the call will fail)
0, NULL, // junk
OPEN_EXISTING, // opens existing pipe
0, NULL); // more junk
if (pipe == INVALID_HANDLE_VALUE) panic("could not connect to the pipe");
// read father's input
for (;;)
{
char buffer[80];
DWORD read = 0;
if (!ReadFile(
pipe,
buffer, // read data
sizeof(buffer)-1, // max length (leave room for terminator)
&read, // bytes actually read
NULL))
break; // exit if the pipe has closed
// display what our father said
buffer[read] = '\0'; // make sure what we just read will be displayable as a string
printf("Father said: %s", buffer);
}
// close pipe
CloseHandle(pipe);
}
int main(int argc, char *argv[])
{
// wait for a <return> keypress on exit
atexit(getchar);
father(argv[0]);
// decide whether we are the father or the child
//if (!strcmp(argv[0], "child")) child();
//else father(argv[0]);
printf("Done\n");
return 0;
}
The problem is located here:
fprintf(stderr, "***PANIC*** %s\n", msg);
printf("In the child thread: Last Error is %lu\n", GetLastError());
This is a standard Windows programming bug, every programmer makes this mistake once. Just once, this is so hard to diagnose that you'll never forget losing the week of your life trying the discover it.
The underlying issue is the way GetLastError() works. It returns the value of an internal global variable, it is stored in the TEB (Thread Environment Block). It has the so common problem with global variables, every call you make to a winapi function is liable to change it, including ones that don't actually fail. Windows itself uses the variable as well. And ERROR_INVALID_NAME is a very popular internal error code.
This is compounded by you not being able to see these winapi calls being made. What is ruining the error code is fprintf(). It is implemented in the CRT with winapi calls. Necessarily so, I/O is an operating system duty.
So what is absolutely essential is that you immediately obtain the error code, before you do anything else. While it is preferable that you pass the value to your panic() function, since it cannot predict what other code runs before it, the quick fix is to rewrite it like this:
int err = GetLastError();
fprintf(stderr, "***PANIC*** %s\n", msg);
printf("In the child thread: Last Error is %lu\n", err);
You'll now get the true error code, the one produced by CreateNamedPipe(). Ought to give you a much better shot at diagnosing the problem. Update your question if you still have a problem interpreting it.

SDL access violation

I have a big program that is causing me access violation when using sdl_rwops. So I decided to create a small program just to test sdl_rwops and it is causing me the same access violation. For what I could see it is being caused because of the fopen_s() part but I could not figure out why.
Maybe you guys can find what I am missing.
Here is the code:
#include "SDL.h"
#include < stdio.h >
int main(int argc, char *argv[])
{
FILE *file;
SDL_Surface *screen;
SDL_Surface *one;
SDL_Rect rect;
errno_t err;
/* This is the RWops structure we'll be using */
SDL_RWops *rw;
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
screen = SDL_SetVideoMode(640, 480, 16, SDL_DOUBLEBUF);
/* Here we get a file pointer to a bitmap */
if ( (err = fopen_s(&file,"penguin.bmp", "r")) != 0)
{
printf("Couldn't load penguin.bmp\n");
exit(1);
}
/* This is where we actually create our RWops structure. Here we're
instructing SDL to get it from the file pointer we just opened */
rw = SDL_RWFromFP(file, 0);
/* SDL_LoadBMP_RW is the RWops version of the old standby,
SDL_LoadBMP. This will get the image from the RWops you passed
in; in this case the file you've opened */
one = SDL_LoadBMP_RW(rw, 0); // This line calls fopen.c and causes the crash
/* Clean up after ourselves */
SDL_FreeRW(rw);
fclose(file);
/* Haphazard way of getting stuff to the screen */
rect.x = rect.y = 20;
rect.w = one -> w;
rect.y = one -> h;
SDL_BlitSurface(one, NULL, screen, &rect);
SDL_Flip(screen);
SDL_Delay(3000);
}
And here is the portion of fopen.c that causes the crash of the program:
errno_t __cdecl _tfopen_s (
FILE ** pfile,
const _TSCHAR *file,
const _TSCHAR *mode)
{
_VALIDATE_RETURN_ERRCODE((pfile != NULL), EINVAL);
*pfile = _tfsopen(file, mode, _SH_SECURE); // This line causes the access violation
if(*pfile != NULL)
return 0;
return errno;
}
The line
one = SDL_LoadBMP_RW(rw, 0);
jumps to fopen.c and the line
*pfile = _tfsopen(file, mode, _SH_SECURE);
in that file makes it crash.
I am using Visual Studio 2012 and the picture is in the same folder as the executable. The SDL.dll and even SDL_image.dll are there too.
I found a post in google of the same issue and the person said that when he put the whole path (instead of just penguin.bmp") it would not crash. It did not work for me, crashed anyway.
I am starting to think that it may be some SDL initialization issue but I did anything I could find on google and nothing worked. I tryed running in Multi-threaded DLL (/Md), in Multi-threaded Debug Dll (/MDd), tryed running in 64 bits, tyred changing the Subsystem to Windows and to console... everything resulted in the same crash.
If you read the documentation of SDL_RWFromFP
Description
SDL_RWFromFP creates a new SDL_RWops structure from a file pointer, opened with stdio. If autoclose is nonzero, the file will be automatically closed when the RWops structure is closed.
Note: This is not available under Win32, since files opened in an application on that platform cannot be used by a dynamically linked library.
Note: This function is not present in SDL-1.2-svn4446
So you need to use SDL_RWFromFile if you want to use RWOps.
Also SDL 2 has many improvements over SDL 1.* and I would highly recommend switching to that.

Resources