gpt4 book ai didi

c - ICU u_fgetfile 与 VS2012 发布版本中的运行时不兼容

转载 作者:太空狗 更新时间:2023-10-29 16:52:43 28 4
gpt4 key购买 nike

我正在尝试将从 u_fgetfile 返回的句柄传递给 fseek/fread 函数。

将我的应用程序与调试运行时库 (/MTd/MDd) 链接时没有崩溃,但如果我链接到静态版本,这个简单的代码会崩溃:

#include <stdio.h>
#include "unicode\ustdio.h"

int main()
{
UFILE* file;
file = u_fopen("C:\\test.txt","r",NULL,"UTF-8");
fseek(u_fgetfile(file),3,SEEK_SET);
}

现在 ICU 的官方构建和我使用 Visual Studio 2012 构建自定义构建时都会发生这种情况(在调试或发布中构建 ICU 并不重要)。

我唯一发现的是 FILE 结构似乎有些不匹配,但我真的不知道。

编辑:

作为向这个问题添加赏金的一部分,这里有一个功能齐全的 VS2012 项目,其中包含复制器程序(与上面发布的代码相同)和带有源代码和二进制文件的 icu。在这里获取:http://goo.gl/urTuU

最佳答案

在我看来,问题出在 _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 返回的指针将进入底层分支。这里假设它是一个 _FILEX*,这很可能根本不正确。

如我们所见,运行时比较文件指针 fb 是否在 _iob 内。但是,在调试器中,我们可以清楚地看到它远远超出了它(至少在发布版本中)。

鉴于 u_fgetfile 仅返回一个存储在 UFILE 结构中的 FILE*,我们可以检查 finit_ownerufile.c 中查看 FILE* 是如何首先出现在我们的结构中的。阅读该代码后,我必须假设在发布版本中,CRT 中存在 _iob 数组的两个独立实例,但在调试版本中,仅存在一个实例。

要解决此问题,您需要确保 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*,但失败了,因为它们有用于 FILE* 的单独存储区域。我觉得这有点令人困惑,但我对所涉及的组件没有必要的了解(Windows C 运行时代码的风格也无济于事)。

因此,如果 FILE* 分配在 ICU 中,那么您不能在主应用程序中锁定它,反之亦然(尝试读取或查找将始终涉及锁定)。

除非这个问题有一个非常明显的解决方案,我会建议在你的主应用程序中模拟 u_fgets() (或任何你需要的)的行为.
据我所知,u_fgets() 只是调用 fread() 从文件中读取数据,然后使用 ucnv_toUnicode(),与转换器存储在 UFILE 中(您可以使用 u_fgetConverter() 检索),以将读取的数据转换为 UChar*

似乎可行的一种方法是静态链接 ICU。我不知道这是否适合您,但它似乎可以解决我的问题。

我下载了最新版本的 ICU (51.2) 并用 this helpful script 编译了它.然后我将该项目与 icu-release-static-win32-vs2012 中的库链接(链接到 sicuuc.libsicuio.libsicudt.lib, sicuin.lib).

现在 u_fgets() 不再导致访问冲突。当然,现在我的 .exe 差不多有 23 MB 了。

关于c - ICU u_fgetfile 与 VS2012 发布版本中的运行时不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17535976/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com