fseek internally calls _invalid_parameter_noinfo when mixing C and C++

59 views Asked by At

I have the following (minimal example) library:

#include "filesizelib.h"

long get_size_example(FILE* file)
{
    printf("Called.\n");
    fseek(file, 0L, SEEK_END);
    printf("SEEK_END finished.\n");
    long file_size = ftell(file);
    fseek(file, 0L, SEEK_SET);
    printf("SEEK_SET finished.\n");
    return file_size;
}

(NOTE: get_size_example assumes the given file was already opened via fopen with rb mode.)

filesizelib.h is as follows:

#pragma once

#include <stdio.h>

#ifdef __cplusplus
extern "C"
{
#endif

__declspec(dllexport) long get_size_example(FILE* file);

#ifdef __cplusplus
}
#endif

And here's how I compile the library (with debug info):

cl /LD /Zi filesizelib.cpp

It compiles successfully. Now we need a C test program (main.c):

#include "lib/filesizelib.h"

#include <stdlib.h>

int main(int argc, char **argv)
{
    FILE* file = fopen("MyBinaryFile.bin", "rb");
    if (!file)
    {
        printf("Unable to open the binary file in rb mode!\n");
        return EXIT_FAILURE;
    }
    long file_size = get_size_example(file);
    printf("File size: %ld\n", file_size);
    fclose(file);
    return EXIT_SUCCESS; 
}

Compilation:

cl main.c /Zi /link filesizelib.lib /LIBPATH:lib

This also compiles successfully, and generates main.exe.

Running main.exe, however, yields a crash on the library's (filesizelib) code. Namely here...

fseek(file, 0L, SEEK_END);

How can I ensure that the call to fseek does not crash? Windows seems to be invoking _invalid_parameter_noinfo as a result of this call. Is this due to mixing C code with a C++-based library?

Additional context: I'm working on a project whose codebase (for the most part) is in C++, yet the client requires that the SDK provide an API in C.

Do note that, if all the code is scoped to a single C program, it seems to work:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    FILE* file = fopen("MyBinaryFile.bin", "rb");
    if (!file)
    {
        printf("Unable to open the binary file in rb mode!\n");
        return EXIT_FAILURE;
    }
    long file_size = 0L;
    printf("Called.\n");
    fseek(file, 0L, SEEK_END);
    printf("SEEK_END finished.\n");
    file_size = ftell(file);
    fseek(file, 0L, SEEK_SET);
    printf("SEEK_SET finished.\n");
    printf("File size: %ld\n", file_size);
    fclose(file);
    return EXIT_SUCCESS; 
}

Output:

Called.
SEEK_END finished.
SEEK_SET finished.
File size: 1741
0

There are 0 answers