Jeff
Jeff

Reputation: 21

Segmentation fault from pointer in fprintf

I am trying to run a program that takes an input file, reads it, and then runs a simulation based on the parameters specified in the input file. The code is a mixture of C and Fortran77, with the main executable entirely in Fortran77. I did not write the code and I'm inexperienced with both languages (so if I say something stupid, that's why).

Upon running the program, I get the following error regardless of the input file: Segmentation fault (core dumped)

This is the output I get from valgrind, with a few small omissions:

Invalid read of size 4
at 0x55ACFDD: vfprintf (vfprintf.c:1295)
by 0x55B76B6: fprintf (fprintf.c:32)
by 0x578C64: cfprintf_ (in [path omitted])
by 0x56D288: writebuf_ (writebuf.F:22)
by 0x56D3CC: writemsg_ (writemsg.F:15)
by 0x4C09E7: init0_ (init0.F:68)
by 0x4D6C65: [omitted]
by 0x4E9EC4: main (main.c:113)
Address 0xffffffff0592bbc0 is not stack'd, malloc'd or (recently) free'd


Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0xFFFFFFFF0592BBC0
at 0x55ACFDD: vfprintf (vfprintf.c:1295)
by 0x55B76B6: fprintf (fprintf.c:32)
by 0x578C64: cfprintf_ (in [path omitted])
by 0x56D288: writebuf_ (writebuf.F:22)
by 0x56D3CC: writemsg_ (writemsg.F:15)
by 0x4C09E7: init0_ (init0.F:68)
by 0x4D6C65: [omitted]
by 0x4E9EC4: main (main.c:113)
If you believe this happened as a result of a stack
overflow in your program's main thread (unlikely but
possible), you can try to increase the size of the
main thread stack using the --main-stacksize= flag.
The main thread stack size used in this run was 8388608.

HEAP SUMMARY:
 in use at exit: 11,354 bytes in 7 blocks
total heap usage: 46 allocs, 39 frees, 22,590 bytes allocated

LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 8,008 bytes in 2 blocks
still reachable: 3,346 bytes in 5 blocks
suppressed: 0 bytes in 0 blocks
Rerun with --leak-check=full to see details of leaked memory

For counts of detected and suppressed errors, rerun with: -v
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

It seems the vfprintf.c and fprintf.c files are part of some internal library, because I can't find those files on my computer. cfprintf.c is part of my code, shown below:

#include <stdio.h>
#include <fcntl.h>

#ifdef _CRAY
#ifdef FORTRAN_PASSES_ASSUMED_CHAR_LEN 
int CFPRINTF (fileptr, s1, cl1, num_chars)
int *cl1;
#else 
int CFPRINTF (fileptr, s1, num_chars)
#endif 
#else
#ifdef POST_UNDERSCORE
int cfprintf_ (fileptr, s1, num_chars)
#else
int cfprintf (fileptr, s1, num_chars)
#endif
#endif

/* write num_chars characters from string s1 to file associated with fileptr */
FILE **fileptr;
char *s1;
int *num_chars;

{
  char format_string [11];
  char buffer[256];
  sprintf (format_string, "%c.%ds", '%', *num_chars);

  /* write to an intermediate buffer to avoid problems with '\n' */
  sprintf (buffer, format_string, s1);
  fprintf (*fileptr, "%s\n", buffer);
}

The line that throws the error is fprintf (*fileptr, "%s\n", buffer); Specifically, I think it's the pointer that is causing the error, but I don't what's wrong or how to fix it.

I had issues compiling the code initially because I am using a 64-bit machine. The code, which relies heavily on pointers, implicitly declares many if not all of them, so I think that means they take the default 32-bit format of 4-bit integers. However, on my machine these pointers are 8-bit integers because I compiled in 64 bits.

If *fileptr is of one format, but the code is expecting another, perhaps that is what's generating the Invalid read of size 4 message from valgrind? But like I said, if that's the problem I still don't know how to fix it.

Thanks for your help, and please let me know if there's any additional code I should post.

Upvotes: 2

Views: 2026

Answers (2)

mctylr
mctylr

Reputation: 5169

As I understand from your question, the application has been known to work in the past, but compiled on 32-bit Unix systems? (That's the only environment I've seen old Fortran and C code mixed in a single program in general.)

Unless you want to port the application to 64-bit I would suggest you simply compile it as an 32-bit native application, assuming your operating system allows 32-bit applications to run in a 64-bit environment.

For example using the gcc compiler the flag -m32 is all you need to add for 64-bit x86 processor systems. I believe clang supports the same flag, but if not check the documentation.

A second potential complicating factor, is whether the program / application (or its data) is endian dependent, which may be an issue if was written under the assumption of being run on BIG ENDIAN CPUs, such as the majority of Unix workstations with RISC-style processors (MIPS, PowerPC, etc.), and you are now trying to run it on an 64-bit x86 Intel or AMD processor (aka amd64, x86-64).

My advice in this case is to hurt someone..., er, review the important of the application and its usage.

Upvotes: 0

nneonneo
nneonneo

Reputation: 179552

First of all, you definitely shouldn't be constructing your format string at runtime like that. Use the following instead:

snprintf(buffer, 256, "%.*s", *num_chars, s1);

or even just

fprintf(*fileptr, "%.*s\n", *num_chars, s1);

.* allows the width of the string to be dynamically specified.

Next, I would check that your fileptr is valid, and that it was successfully opened. The address 0xffffffff0592bbc0 is very suspicious due to the four high bytes all being 0xff, so it is possible that you are having 32-bit/64-bit issues.

Upvotes: 1

Related Questions