返回
C/C++ 混合编程中 fseek 导致 _invalid_parameter_noinfo 异常的解决方法
windows
2024-03-27 02:22:33
C 和 C++ 混合编程中使用 fseek 时的 _invalid_parameter_noinfo 异常
问题
在 C 和 C++ 混合编程时,使用 fseek
函数可能会导致 _invalid_parameter_noinfo
异常。这是因为 C 和 C++ 使用不同的 FILE
结构。
问题分析
DLL 导出文件指针
假设我们有一个 DLL,其中包含一个导出函数 exportedFunction
。该函数使用一个由应用程序初始化的文件指针 pFile
进行 fprintf
操作。
文件指针不匹配
问题在于应用程序和 DLL 使用不同的 _iob[]
数组,其中包含文件指针。这会导致 pFile
在应用程序和 DLL 中指向不同的文件位置。
解决方案
为了解决这个问题,我们需要在应用程序和 DLL 中使用相同的文件指针数组。
在 DLL 中显式加载 _iob[]
在 DLL 中,我们可以使用 __imp__iob
导入应用程序的 _iob[]
数组:
#ifdef BUILD_FOO
# define FOOAPI __declspec(dllexport)
#else
# define FOOAPI __declspec(dllimport)
#endif
FOOAPI extern FILE* __imp__iob[];
FOOAPI void exportedFunction();
在 DLL 中使用导入的 _iob[]
在 exportedFunction
中,我们可以使用 __imp__iob[]
而不是 pFile
:
void exportedFunction()
{
fprintf(__imp__iob[0], "This will result in an exception\n");//<-This print will crash
}
在应用程序中显式导出 _iob[]
在应用程序中,我们可以使用 __declspec(dllexport)
导出 _iob[]
数组:
#undef BUILD_FOO
#include "API.H"
#pragma warning(disable : 4100) // disable warnings for using an unnamed extern
extern FILE* __declspec(dllexport) __iob[];
改进后的代码
DLLFile.c
#define BUILD_FOO
#include "API.H"
void exportedFunction()
{
fprintf(__imp__iob[0], "This will result in an exception\n");//<-This print will crash
}
API.H
#ifdef BUILD_FOO
# define FOOAPI __declspec(dllexport)
#else
# define FOOAPI __declspec(dllimport)
#endif
FOOAPI extern FILE* __imp__iob[];
FOOAPI void exportedFunction();
APPLICATION.C
#undef BUILD_FOO
#include "API.H"
void main()
{
#pragma warning(disable : 4100) // disable warnings for using an unnamed extern
extern FILE* __declspec(dllexport) __iob[];
pFile = fopen("path_to_folder","wt");
fprintf(pFile , "This print will work"); // <- This will be printed ok
exportedFunction();
}
结论
通过使用相同的文件指针数组,我们解决了在 C 和 C++ 混合编程时使用 fseek
时遇到的 _invalid_parameter_noinfo
异常。
常见问题解答
1. 为什么会出现 _invalid_parameter_noinfo
异常?
- 因为 C 和 C++ 使用不同的
FILE
结构,导致文件指针不匹配。
2. 如何修复此异常?
- 在应用程序和 DLL 中使用相同的文件指针数组。
3. 如何在 DLL 中导入 _iob[]
数组?
- 使用
__imp__iob
导入应用程序的_iob[]
数组。
4. 如何在应用程序中导出 _iob[]
数组?
- 使用
__declspec(dllexport)
导出_iob[]
数组。
5. 还有什么需要注意的吗?
- 确保在应用程序和 DLL 中使用相同的编译器和库版本。