我使用DDS实用程序加载Nvidia nv_dds图像文件,以便在OpenGL程序中使用。它可以在Windows上工作,但在Linux (Ubuntu12.10)上失败。我原以为是nv_dds的问题,但后来发现在Linux上fread()读取带有错误偏移量的头字节(GCC 4.7)。
这是读取DDS文件标记,然后读取DDS标头的块:
// open file
FILE *fp = fopen(filename.c_str(),"rb");
if (fp == NULL) {
return false;
}
// read in file marker, make sure its a DDS file
char filecode[4];
fread(filecode, 1, 4, fp);
if (strncmp(filecode, "DDS ", 4) != 0) {
fclose(fp);
return false;
}
// read in DDS header
DDS_HEADER ddsh;
fread(&ddsh, 1,sizeof(DDS_HEADER) , fp);当我查看DDS_HEADER实例的内容时,我可以看到一些实值分配给了错误的属性,其余的都是垃圾。
然后,如果我注释掉"DDS“标记,请检查fread():
// open file
FILE *fp = fopen(filename.c_str(), "rb");
if (fp == NULL) {
return false;
}
// read in file marker, make sure its a DDS file
/* comment out for test
char filecode[4];
fread(filecode, 1, 4, fp);
if (strncmp(filecode, "DDS ", 4) != 0) {
fclose(fp);
return false;
}
*/
// read in DDS header
DDS_HEADER ddsh;
fread(&ddsh, sizeof( DDS_HEADER ),1 , fp);//sizeof( DDS_HEADER )然后我将图像宽度值放入DDS_HEADER.The的imageHeight属性中,其余的属性仍然是垃圾。
当我在Windows机器上测试它时,所有这些都不会发生。有没有可能fread()在带有MSVC编译器的Linux和Windows上的工作方式不同?
发布于 2013-05-21 16:22:08
我解决了这个问题,因为没有提出有用的输入,所以我将自己回答这个问题。
我发现了这个post,我开始怀疑不同compilers.Then之间数据类型大小的差异。之后,我发现DDS header的大小(用GCC编译)是248,这是正常大小的两倍。(微软规范说它必须是124字节).nv_dds dds header使用unsigned long作为其成员:
typedef struct
{
unsigned long dwSize;
unsigned long dwFlags;
unsigned long dwHeight;
unsigned long dwWidth;
unsigned long dwPitchOrLinearSize;
unsigned long dwDepth;
unsigned long dwMipMapCount;
unsigned long dwReserved1[11];
DDS_PIXELFORMAT ddspf;
unsigned long dwCaps1;
unsigned long dwCaps2;
unsigned long dwReserved2[3];
}DDS_HEADER;因此,MSVC编译器将无符号的长整型视为4字节,而在Linux8 bytes.From上的GCC则是报头的两倍大小。我将其全部更改为unsigned int (也在DDS_PIXELFORMAT标头中):
typedef struct
{
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwHeight;
unsigned int dwWidth;
unsigned int dwPitchOrLinearSize;
unsigned int dwDepth;
unsigned int dwMipMapCount;
unsigned int dwReserved1[11];
DDS_PIXELFORMAT ddspf;
unsigned int dwCaps1;
unsigned int dwCaps2;
unsigned int dwReserved2[3];
}DDS_HEADER;因此,似乎与某些地方所说的相反,NVidia nv_dds不是跨平台的(或/和交叉编译读取),应该进行这种攻击,以使其在Linux上与GCC一起工作。
发布于 2013-06-20 01:49:27
对于GCC来说,32位编译时是4字节,64位编译时是8字节。可以使用选项-m32或-m64显式目标32位或64位。
发布于 2013-08-21 08:37:25
对于ABI相关的任务,你应该总是使用在stdint.h中定义的类型名中描述其大小的类型,比如int32_t/uint64_t,这样可以在不同的平台上编译时省去很多问题。(除了大/小端问题)
https://stackoverflow.com/questions/16645040
复制相似问题