移植工作開始后的第一步就是在目标平台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编译器的区别的更多相关文章

  1. 【转载】LINUX 和 WINDOWS 内核的区别

    LINUX 和 WINDOWS 内核的区别 [声明:欢迎转载,转载请注明出自CU ACCESSORY http://linux.chinaunix.net/bbs/thread-1153868-1-1 ...

  2. 从Docker在Linux和Windows下的区别简单理解Docker的层次结构

    上篇文章我们成功在Windows下安装了Docker,输出了一个简单的Hello World程序.本文中我们将利用Docker已有的云端镜像training/webapp来发布一个简单Python的W ...

  3. 深度剖析Linux与Windows系统的区别

    当我们每个人接触Linux之前,应该先接触的都是windows吧?但我们一般接触Linux后,习惯linux的管理和使用方法后,我们再回过头再来使用windows的时候,内心其实是拒绝的.我们会觉得图 ...

  4. 深度剖析Linux与Windows系统的区别,新手必读!

    当我们每个人接触Linux之前,应该先接触的都是windows吧?但我们一般接触Linux后,习惯linux的管理和使用方法后,我们再回过头再来使用windows的时候,内心其实是拒绝的.我们会觉得图 ...

  5. linux和windows系统的区别

    在21世纪的今天,互联网可以说是当代发展最为迅速的行业,举个很简单的例子,现在的我们不论什么年龄阶层,几乎人手都有一部手机,上面的某博,某音,末手等软件,更是受到多数人的热爱,并且人们不仅仅用其来消遣 ...

  6. linux与Windows使用编译区别及makefile文件编写

    一.Windows与:Linux嵌入式开发区别 Windows下编辑.编译.执行 编辑: sourceInsight:ADS: 编译:指定链接地址,指定链接顺序,编译 执行:烧写到单板再启动 Linu ...

  7. python+unittet在linux与windows使用的区别

    使用python的unittest编写单元测试框架,批量运行测试用例时,如果使用discover时,windows环境下和linux环境下的代码不一样 Windows环境的run.py代码: case ...

  8. 日期在Linux与Windows下的区别

    最近遇到了这个问题,就是相同的代码在Windows与Linux下的日期转换不一致. 原因:时区问题,主要是操作系统与JVM中的时区不同导致的 在网上查了很多处理的方法:最后总结出一条简单粗暴的方法:原 ...

  9. Linux和Windows系统目录结构区别

    Windows目录结构图 Linux目录结构图 我们所有的操作尽量都要在/home/username目录下进行. 快捷进入家目录方式是cd ~.

随机推荐

  1. mui 本地打包

    第一步:下载HBuilder离线打包Android版SDK 网址:http://ask.dcloud.net.cn/article/38 第二步:导入项目 启动带ADT的eclipse程序,菜单中选择 ...

  2. search-a-2d-matrix——二维矩阵找数

    题目描述 Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the ...

  3. C++ 模板详解(二)(转)

    四.类模板的默认模板类型形参 1.可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值.函数模板和类模板都可以为模板的非类型形参提供默认值. 2.类模板的类型形参默认值形式为:tem ...

  4. 《Android源代码设计模式解析与实战》读书笔记

    1.定义 将对象组合成树形结构以表示"部分-总体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性. 2.使用场景 (1)表示对象的部分-总体层次结构时. (2)从一个总体 ...

  5. 3、Linux内核模块学习

    一.内核模块的学习   内核的整体框架是非常的大,包含的组件也是非常多,如何将需要的组件包含在内核中呢?选择一,就是将所有的组件全部编译进内核,虽然需要的组件都可以使用,但是内核过分庞大,势必带来效率 ...

  6. 转:Exception loading sessions from persistent storage

    直用tomcat一段时间都正常无事,最近一次启动tomcat就发生以下异常: 严重: IOException while loading persisted sessions: java.io.EOF ...

  7. hdu 1159(Common Subsequence)简单dp,求出最大的公共的字符数

    Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  8. 使用wifi连接eclipse进行android程序调试

    首先手机必须是root过的.能够使用百度一键root工具. 然后,在手机中打开这个终端(terminal)应用,输入例如以下命令:         su         setprop service ...

  9. 【问题记录】mysql设置任意ip访问

    # 给username用户授予可以用任意IP带密码password访问数据库 GRANT ALL PRIVILEGES ON *.* TO 'username'@'%'IDENTIFIED BY 'p ...

  10. [译]NeHe教程 - 创建一个OpenGL窗体

    原文: Setting Up An OpenGL Window 欢迎阅读我的OpenGL教程.我是一个热爱OpenGL的普通码农!我第一次听到OpenGL是在3Dfx刚发布他们给Voodoo I显卡的 ...