Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ICU u u_fgetfile与VS2012版本中的运行时不兼容_C_Visual Studio 2012_Icu_Visual C++ - Fatal编程技术网

ICU u u_fgetfile与VS2012版本中的运行时不兼容

ICU u u_fgetfile与VS2012版本中的运行时不兼容,c,visual-studio-2012,icu,visual-c++,C,Visual Studio 2012,Icu,Visual C++,我正在尝试将从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_fge

我正在尝试将从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);
}
#包括
#包括“unicode\ustdio.h”
int main()
{
UFILE*文件;
file=u_fopen(“C:\\test.txt”,“r”,NULL,“UTF-8”);
fseek(u_fgetfile(file),3,SEEK_SET);
}
现在,ICU的正式版本和我使用Visual Studio 2012构建自定义版本时都会发生这种情况(在调试或发布中构建ICU并不重要)

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

编辑:


作为对这个问题的补充,这里有一个功能齐全的VS2012项目,它包含了复制程序(与上面发布的代码相同)和带有源代码和二进制文件的icu。在这里获取:

第一个问题:是否可以编译和使用c++11功能(因为这样我们将有更多的工具来分析实际发生的事情)

第一件事是尝试使用以下代码查看文件结构内部:

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

int main()
{
    unsigned int size = sizeof(FILE);
    FILE* file = fopen("main.c", "r");
    unsigned int i = 0;
    unsigned char buffer[size];
    memcpy(buffer, file, size);
    printf("The %u bytes at address %p are: \n", size, file);
    for (i = 0; i < size; ++i) {
        printf("%02X ", (unsigned int)(buffer[i]));
        if ((i+1)%64 == 0) {
            printf("\n");
        }
    }
    printf("\n");
    fclose(file);
    return 0;
}
#包括
#包括
#包括
int main()
{
unsigned int size=sizeof(文件);
FILE*FILE=fopen(“main.c”、“r”);
无符号整数i=0;
无符号字符缓冲区[大小];
memcpy(缓冲区、文件、大小);
printf(“地址%p处的%u字节为:\n”、大小、文件);
对于(i=0;i
对于两个不同的文件以及调试库和静态库,用
UFILE
替换
FILE
,用
u\u fopen
替换
fopen
函数


它将显示文件结构的字节,也许我们将了解有关问题所在的有用信息。

您的问题是由于链接到了错误的库

我用官方的ICU和VS2010复制了完全相反的结果,发布版本在调试版本崩溃时工作

问题是(IMHO)链接到调试和发布VC运行时,并在不同版本的函数之间传递文件指针。版本中来自fopen的结果在调试中传递给fseek。在区分_iob和FILEX文件(不同的_iob_条目)方面,它们似乎不兼容


将调试项目与发行版ICU链接,反之亦然,将导致此问题。

在我看来,问题似乎存在于
\u lock\u文件中,其中说明:

    /*
     * 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) );

关于在此之后出现的问题,在我看来,根本的问题只是在库之间共享一个
文件*
,这失败了,因为它们有单独的
文件*
存储区域。我觉得这有点令人困惑,但我对涉及的组件没有必要的了解(而且WindowsC运行时代码的风格也没有帮助)

因此,如果
文件*
是在ICU中分配的,那么您不能在主应用程序中锁定它,反之亦然(尝试读取或查找总是需要锁定)

除非这个问题有一个非常明显的解决方案(我没有找到),否则我建议您在主应用程序中模拟
u\u fgets()
(或您需要的任何其他东西)的行为。
据我所知,
u\u fgets()
只需调用
fread()
从文件中读取数据,然后使用
ucnv\u toUnicode()
,转换器存储在
UFILE
中(您可以使用
u fgetConverter()
检索),将读取的数据转换为
UChar*

一种似乎有效的方法是静态链接ICU。我不知道这是否是你的选择,但它似乎解决了我这边的问题

我下载了ICU的最新版本(51.2),并用编译工具进行了编译。然后,我将项目与
icu-release-static-win32-vs2012
中的库相链接(链接
sicuuc.lib
sicuio.lib
sicudt.lib
sicuin.lib

现在
u\u fgets()
不再导致访问冲突。当然,现在我的
.exe
几乎有23MB大。

问题是“icuio51.dll”(Release)与静态CRT链接!因此,它与共享CRT不共享同一个文件指针!这就是为什么它在“锁”中崩溃的原因

另一方面:`icuio51d.dll´(调试)与相同的共享CRT(msvcr110d.dll)链接,因此使用相同的共享文件*指针

这就是它在“调试”中工作而不是在“发布”中工作的原因

解决方案:您必须使用正确的设置重新编译ICU,以便始终使用“共享CRT”(/MD和/MDd)。。。 为此,您必须执行以下步骤:

  • 打开解决方案“allinone\allinone.sln”
  • 编辑项目“io”的属性
  • 将“Win32”平台的“C/C++|代码生成|运行时库”从“多线程(/MT)”更改为“多线程DLL(/MD)”(x64似乎是正确的!)
  • 重新编译您的项目

  • 我确信您测试了这个,但只是为了完整性:
    u\u fopen()
    u\u fgetfile()
    不要返回
    NULL
    ,不是吗?我已经测试过了,所以不是。icu和我的程序之间似乎存在某种文件结构不匹配。
    文件
    中定义,这两个版本(libicu和测试应用程序)应该是相同的。你确定你的版本没有混合32位和64位版本吗?是的,它们应该是相同的,但是很明显句柄有问题。我甚至不知道这是如何工作的,当然如果我尝试链接一个64位的libi
    FILE* filePointer = fopen("test.txt","r");
    UFILE* file = u_finit(filePointer,NULL,"UTF-8");
    
    fseek(filePointer,3,SEEK_SET); // <- won't crash