Linux与Windows编译器的区别

简介:

移植工作開始后的第一步就是在目标平台Linux上进行编译,并链接源码。因为须要移植的软件通常并未在Linux平台上编译过,编译的过程可能会遇到非常大的困难。普通情况下,由类型声明引起的编译错误是比較easy修复的。比方Microsoft C/C++的头文件使用__declspec( dllimport/dllexport )来输入和输出DLL函数,在Linux上,把函数声明成extern “C”,或者再结合使用DEF文件,使用对应的链接命令就能够解决这些问题。但困难的地方在于编译器之间存在差异的部分,同一时候这也是可能引起非常多执行时问题的重要因素,读者有必要在開始移植之前就充分了解。在此讲述一些easy被忽略而且后果比較严重的方面。

以Visual C++ 2003和GCC 4.1.0为例。前者是Windows平台的主流编译器,兼容性良好,可是对C++标准的遵循并不严格。这意味着即使开发人员写出不太符合标准的程序,编译器也可能能容忍。相反的是,GCC对标准的遵循相对严格得多,这样非常easy造成在Windows执行良好的程序,在Linux上却引起意想不到的编译甚至执行时错误。

(1)基本类型大小和结构对齐

首先是 C/C++语言基本类型的大小,以及对应的结构对齐问题。典型的样例是longkeyword。在Visual C++ 2003下,sizeof(long double)是8,其大小和double一致。可是在GCC 4.1.0上,sizeof(long double)等于12,其大小比double多4。还有一个和大小相关的问题是对齐问题。不同编译器的默认对齐大小是不一样的。普通情况下程序逻辑都跟对齐无关,可是涉及从磁盘或者网络文件里读取结构时(如解析资源),精确的对齐就是必需的。考察以下的程序段:

#include 
struct A

{
char a;
double b;
};

int main()
{
printf("%d %d %d\n", sizeof(long double), 
sizeof(long long), sizeof(A) );
return 0;
}

上面这段程序在 Visual C++ 2003编译器默认设置下,输出结果为8 8 16;在GCC 4.1.0编译器默认设置下,其输出为12 8 12。从sizeof(A)的大小能够看出,Visual C++ 2003是按8字节对齐的,而gcc是4字节对齐的。这时须要使用#pragma pack预编译指令来改动头文件里的结构声明,或者在执行时调整内存中结构成员的位置。无论採用何种方法,对齐都是须要小心处理的事情。

一个引起最大麻烦的基本类型是wchar_t。在Visual C/C++ 2003编译器中,wchar_t的大小是2字节,而且能够和unsigned short类型互相赋值。与此关联的一系列Unicode相关函数,比方wcslen,wcscmp等,都接受UTF16格式的Unicode串。在 GCC中,其大小是32位。与此相关的wcslen,wcscmp函数都接受UTF32格式的Unicode串。为此,必须在Linux上开发一套 UTF16接口的wcs系列函数,以保证UTF16的字符串被正确处理。与此同一时候,使用宏定义来替换wchar_tkeyword为unsigned short,以保证函数声明的兼容。

(2)new操作符的出错处理

还有一个问题是new操作符的出错处理。因为编译器的设置不同,new操作符可能具有不同的行为。考察例如以下的代码段:

#include 
class A
{
public:
void *operator new( size_t size )
{
return NULL;
}
A()
{
printf("Constructor called\n");
a = 0;
}
private:
int a;
};

int main()
{
A *p = new A();
printf("%x\n", p );
return 0;
}

在Visual C++ 2003中,上面的程序输出0。而GCC 4.1.0编译器的输出结果为:

Constructor called
Segmentation fault

也就是说,Visual C++ 2003的编译器会检查new的返回值,假设返回为空,构造函数就不再执行。可是gcc必须加上–fcheck-new编译參数才具有这一行为:g++ –fcheck-new test.cpp。这样在Linux上上述程序也会输出0。

(3)结构化异常和C++异常

还有一个更隐蔽的差异存在于异常处理。Visual C++并不遵循异常处理的C++规范。考察例如以下的程序段:

#include 
int main()
{
int* p = NULL;
try
{
*p = 0;
}
catch (...)
{
printf("caught the exception\n");
return 1;
}
return 0;
}
读者能够自己用 Visual C++ 2003和GCC分别检验这段程序。前者生成的程序在Windows上正常执行,输出caught the exception,然后正常退出。而GCC生成的程序仅仅是输出Segmentation fault。所以在Windows上,catch语句抓住了一个异常。依照C++的标准,唯独使用throw语句,才干产生异常。可是在上面的程序段中, 仅仅是一个简单的赋值语句。原因在于,Visual C++ 2003将C++的异常处理映射成了Windows的结构化异常处理。在上面的语句中,*p = 0将引起一个Windows的异常,Visual C++将它处理成一个C++异常,并进入catch块。在Linux上,因为沒有C++异常发生,程序直接崩溃。

本文转自博客园知识天地的博客,原文链接:Linux与Windows编译器的区别,如需转载请自行联系原博主。


相关文章
|
14天前
|
Linux Windows
Linux01---目录结构,Linux系统下只有一个最顶级的树/,Windows系统有盘符概念,而Linux系统没有盘符概念,整个系统都在/根目录下,Linux 系统写法 /user/local
Linux01---目录结构,Linux系统下只有一个最顶级的树/,Windows系统有盘符概念,而Linux系统没有盘符概念,整个系统都在/根目录下,Linux 系统写法 /user/local
|
29天前
|
自然语言处理 安全 编译器
深入探索Linux下的luac命令:Lua编译器的奥秘
**探索Linux上的`luac`:Lua编译器详解** `luac`是Lua源代码的编译器,将`.lua`转换为字节码`.luac`,提升执行效率。它通过词法、语法分析生成可移植、安全的字节码。主要特点包括高效、可移植和安全。命令参数如`-l`列出字节码结构,`-o`指定输出,`-s`去除调试信息。使用示例:`luac -o script.luac script.lua`,然后用`lua script.luac`执行。注意版本兼容性,开发时保留调试信息,生产环境优化源代码并备份源文件。
|
1月前
|
Ubuntu Linux C语言
【opencv】opencv在windows和linux的应用
【opencv】opencv在windows和linux的应用
|
1月前
|
运维 Linux 网络安全
跨平台SSH文件传输:Linux与Windows环境下的实践指南
本文介绍了在Linux和Windows之间使用SCP、SecureCRT及PuTTY工具集进行文件传输的方法。在Linux中,利用SCP命令进行文件下载、上传及目录传输。在Windows环境下,PSFTP和PSCP提供类似功能,而SecureCRT作为SSH客户端,支持设置上传下载目录并进行文件传输。掌握这些工具的使用可提升跨平台运维效率。
|
16天前
|
Shell Linux
Linux环境变量之shell中export定义全局变量和echo 变量的区别
Linux环境变量之shell中export定义全局变量和echo 变量的区别
|
21天前
|
Linux 数据安全/隐私保护 Windows
pscp 将Linux服务器上的文件同步到Windows服务器上
【6月更文挑战第28天】pscp 将Linux服务器上的文件同步到Windows服务器上
27 0
|
22天前
|
运维 网络协议 Linux
Linux与Windows下追踪网络路由:traceroute、tracepath与tracert命令详解
Linux与Windows下追踪网络路由:traceroute、tracepath与tracert命令详解
33 0
|
23天前
|
NoSQL 编译器 Linux
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
22 0
|
24天前
|
Linux Windows
windows和linux安装Erlang
windows和linux安装Erlang
40 0
|
28天前
|
网络协议 Linux 编译器
【原创】EtherCAT主站IgH解析(二)-- 如何将Igh移植到Linux/Windows/RTOS等多操作系统移植指南
EtherCAT主站方案对比:商业的如Acontis、TwinCAT3和开源的igh、SOEM。SOEM易移植但功能和实时性不足,适合简单应用;igh功能强大,实时性能优秀,基于内核态,适合复杂场景。igh能移植到其他RTOS,但需克服多任务无调度的挑战。依赖操作系统服务如定时器、内存分配,适合Linux内核,但移植到裸机复杂。