在我看来,问题出_lock_file
在它所说的范围内:
/*
* The way the FILE (pointed to by pf) is locked depends on whether
* it is part of _iob[] or not
*/
if ( (pf >= _iob) && (pf <= (&_iob[_IOB_ENTRIES-1])) )
{
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
*/
_lock( _STREAM_LOCKS + (int)(pf - _iob) );
/* We set _IOLOCKED to indicate we locked the stream */
pf->_flag |= _IOLOCKED;
}
else
/*
* Not part of _iob[]. Therefore, *pf is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
EnterCriticalSection( &(((_FILEX *)pf)->lock) );
一个“正常”FILE*
将进入顶部分支,从返回的指针u_fgetfile
将进入底部分支。这里假设它是 a _FILEX*
,这很可能根本不正确。
如我们所见,运行时比较文件指针fb
是否在_iob
. 但是,在调试器中,我们可以清楚地看到它远远超出了它(至少在发布版本中)。
鉴于u_fgetfile
只返回FILE*
存储在UFILE
结构中的 a,我们可以先检查一下finit_owner
,ufile.c
看看FILE*
最终在我们的结构中是如何结束的。阅读该代码后,我必须假设在发布版本_iob
中,CRT 中存在两个单独的数组实例,但在调试版本中,仅存在一个实例。
为了解决这个问题,您需要确保FILE*
在与您的主应用程序相同的线程中创建 。为此,您可以使用u_finit
,如下所示:
FILE* filePointer = fopen("test.txt","r");
UFILE* file = u_finit(filePointer,NULL,"UTF-8");
fseek(filePointer,3,SEEK_SET); // <- won't crash
关于您在此之后出现的问题,在我看来,根本问题只是FILE*
在库之间共享 a ,这会失败,因为它们有单独的存储区域用于FILE*
. 我觉得这有点令人困惑,但我对所涉及的组件没有必要的理解(而且 Windows C 运行时代码的风格也无济于事)。
因此,如果FILE*
在 ICU 中分配 ,那么您不能将其锁定在主应用程序中,反之亦然(尝试读取或查找将始终涉及锁定)。
除非有一个非常明显的解决方案来解决这个问题,否则我会建议u_fgets()
在您的主应用程序中模拟(或您需要的任何其他内容)的行为。
据我所知,u_fgets()
只需调用fread()
从文件中读取数据,然后使用ucnv_toUnicode()
存储在 中的转换器UFILE
(您可以使用 检索u_fgetConverter()
)将读取的数据转换为UChar*
.
一种似乎可行的方法是静态链接 ICU。我不知道这是否适合您,但它似乎解决了我的问题。
我下载了最新版本的 ICU (51.2) 并用这个有用的脚本编译了它。icu-release-static-win32-vs2012
然后,我将项目与(用sicuuc.lib
, sicuio.lib
, sicudt.lib
,链接)中的库链接起来sicuin.lib
。
现在u_fgets()
不再导致访问冲突。当然,现在我.exe
的几乎是 23 MB 大。