0

I have an issue writing into a stream, passed as a FILE* to a function which is contained in a DLL. Compiler: Visual C++, all versions 2005 to 2015. The precise errors vary; the VS 2015 version is given below. The problem is identical for Win32 and x64 targets.

Trying to boil down the problem, consider this function:

#include <stdio.h>
void TestPrintf(FILE *TestFile)
{
    fprintf(TestFile, "Hello World");
}

Now, another function will be calling the above function in the following way:

#include <stdio.h>
void TestPrintf(FILE *TestFile);
void AnyFunction( void )
{
    FILE *TestFile;
    fopen_s( &TestFile, "PrintTest.txt", "wt");
    TestPrintf(TestFile);
}

The first function is part of a DLL. Depending on the settings in Properties / C/C++ / Code Generation during compilation of both the DLL and the program containing the caller, I get the following error messages:

Caller compiled for Multithread Debug (static):
DLL compiled for either Multithread Debug (static) or Multithread Debug DLL:

    Debug assertion failed   
    File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp  
    Line: 980  
    Expression: __acrt_first_block == header  

DLL compiled for Multithread (static):

    Debug assertion failed in the same file as before, but now  
    Line: 892  
    Expression: is_block_type_valid(header->block_use)  

DLL compiled for Multithread DLL:

    Again another variant of the same. Now it is:  
    Line: 888  
    Expression: _CrtlsValidHeapPointer(block)  

Caller compiled for Multithread Debug DLL:
DLL compiled for either Multithread (static) or Multithread Debug (static):

    same messages as above  

DLL compiled for Multithread DLL:

    Yet another variant of the same. Now it is:  
    HEAP[FilePrintTest.exe]: Invalid address specified to RtlValidateHeap( 
    01060000, 0107B7A0 )

DLL compiled for Multithread Debug DLL:

    This is error-free.  

Caller compiled for Release (either Multithread or Multithread DLL):

all four versions of the DLL go error-free.  

The difference between VS versions seems to be that VS 2015 first writes the output as intended and crashes afterwards, whereas VS 2005 crashes already while writing the output.

If the function TestPrintf is not in a DLL, but in a static library, there is no such problem (of course, there will be linker messages about library collisions, but the test program works nonetheless). However, unfortunately, I do need the writing function inside the DLL, and I must be able to call it from anywhere.

All of the above applies also to the case that the caller is in a console programme and the stream is stdout.

So my question is: Is there a stupid mistake on my side? If not, is there a way to work around this problem?

I would be grateful for suggestions!
Martin

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Martin
  • 1
  • 2
  • Please, choose between C and C++. There are different languages – Garf365 Mar 04 '16 at 14:38
  • @Garf365: "Compiler: Visual **C++**" – too honest for this site Mar 04 '16 at 14:40
  • @Olaf but code presented seams C – Garf365 Mar 04 '16 at 14:41
  • 1
    @Garf365: Identical syntax does not imply identical semantics! – too honest for this site Mar 04 '16 at 14:42
  • @Olaf agree with you, but we don't know what want OP – Garf365 Mar 04 '16 at 14:43
  • 1
    @Garf365: To say it very clearly (I tought my first comment already was): If you use a C++ compiler, it **is** C++. You cannot use C semantics or C-only features then. – too honest for this site Mar 04 '16 at 14:45
  • Clearly, someone's corrupting your heap, possibly by overriding some dynamically allocated buffer. The errors you see are printed when they are detected, which isn't necessarily when they are caused. I'd suggest looking for heap errors in general, you can find some suggestions [here](http://stackoverflow.com/q/1010106/26039). – Eran Mar 04 '16 at 15:03
  • Thanks for the comments! – Martin Mar 04 '16 at 18:30
  • @eran: I understand that. However, in the simplified example I posted, there is really nothing else I am doing than calling the function with the fprintf command. So it must be the very buffer memory of the FILE which is corrupted by fprintf, if the latter is called from within the DLL. – Martin Mar 04 '16 at 18:44
  • @Garf365: It is the same in C or C++. To make the example simple, I posted only C code. – Martin Mar 04 '16 at 18:44

1 Answers1

0

Please review the fopen_s syntax. You are passing a FILE * * by using the & in front of the pointer.

Try removing the & symbol:
fopen_s(TestFile, /*...*/);

Your TestFile is already a pointer:

FILE * TestFile;

Your usage doesn't match the syntax presented by cppreference.com

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • 2
    Microsoft requires the syntax with a FILE** variable passed, see here.. This makes sense as a variable of type FILE* must be written. The old fopen did it by returning a value of type FILE*. I humbly suspect there is a typo in cppreference.com. – Martin Mar 04 '16 at 18:51
  • @Martin cppreference documents pointer to pointer to FILE for the first parameter of fopen_s – Cubbi Mar 11 '16 at 14:57