小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

mingw/vc2008移植問題記錄

 云將東游 2018-05-17
關(guān)于VC和gcc的區(qū)別,請參考以下鏈接:

gccとVC(日文)

http://homepage1./herumi/prog/gcc-and-vc.html

 

(20131119)

超初心者のプログラム入門

http://www.eonet./~maeda/index.html

 

 

Problem 1: VC2008 運(yùn)行時庫
屬性頁->C/C++->代碼生成->運(yùn)行時庫(一般是MTd和MT)

 

Problem 2: inline函數(shù)重定義問題,可以考慮用#if屏蔽掉
#if defined(_MSC_VER) && (_MSC_VER < 1500) //VC 9
inline int inet_pton(int af, register const char *cp, struct in_addr *addr)

 

Problem 3: libevent.lib 依賴問題。
如果使用VC2008,并且建立起libevent源代碼工程??梢钥紤]使用“鏈接器->輸入->附加依賴項(xiàng)”,這樣就不再需要添加libevent.lib

 

Problem 4: errno賦值問題
errno = 0需要改為set_errno(0);
原因是vc2008的編譯器在多線程時不允許你直接給errno賦值,貌似是為了線程安全,這時候就得寫個宏。

 

 

C代碼  收藏代碼
  1. #if defined(_MT) || defined(_DLL)  
  2. # define set_errno(x)    (*_errno()) = (x)  
  3. #else  
  4. # define set_errno(x)    errno = (x)  
  5. #endif  

 

 

不知道linux怎么處理線程安全(好像linux根本就不需要這么復(fù)雜)。

 

Problem 5:APR導(dǎo)入問題。
如果有一天突然想用APR或APU來編程,你就得遇到這種囧問題——不知道怎么在vc2008里鏈接。
一種方法是:
宏定義添加
APR_DECLARE_EXPORT(補(bǔ)充:或者APU_DECLARE_EXPORT)
WIN32
確保是動態(tài)導(dǎo)出api和動態(tài)導(dǎo)入APR DLL

附加依賴項(xiàng)目選擇使用動態(tài)鏈接的lib(以防萬一把a(bǔ)pr和apu的都加上)
libapr-1.lib libaprutil-1.lib
如果不知道apr為何物,就最好別管這種復(fù)雜問題(Apache httpd的代碼和API需要高手才看得懂的)
推薦用動態(tài)庫(不會遇到一堆鏈接錯誤)如果用靜態(tài)庫要改用另一套lib和APR_DECLARE_STATIC

 

Problem 6: 函數(shù)聲明和定義不同。
可能vc2008會對類型很敏感。最好改為統(tǒng)一。

 

Problem 7: snprintf問題
Windows SDK沒有snprintf這個函數(shù),用_snprintf代替

 

 

C代碼  收藏代碼
  1. #ifndef snprintf  
  2. #define snprintf _snprintf  
  3. #endif  

 

 

Problem 8: strtoll和strtoull問題

 

 

C代碼  收藏代碼
  1. #if _MSC_VER < 1300  
  2. #define strtoll(p, e, b) ((*(e) = (char*)(p) + (((b) == 10) ? strspn((p), "0123456789") : 0)), _atoi64(p))  
  3. #else  
  4. #define strtoll(p, e, b) _strtoi64(p, e, b)   
  5. #endif  
  6.   
  7. #ifndef strtoull  
  8. #define strtoull strtoul  
  9. #endif  

 

 

遇到這種問題需要查SDK的手冊,你會發(fā)現(xiàn)有個叫_atoi64的API(這個函數(shù)很早就有了,用于32位操作系統(tǒng)上,定義在stdlib.h)。
當(dāng)然如果你不喜歡上面代碼寫得那么復(fù)雜,可以一概改為_atoi64。另外,還需要知道有個關(guān)鍵字__int64,
可以用它表示有符號和無符號的64位整數(shù)(很少出現(xiàn),除非你要用64位來提高性能)
_strtoi64的用法稍微不同。還有個叫_i64toa的API,是_atoi64的逆轉(zhuǎn)換。

 

補(bǔ)充:可能對于64位整數(shù),還要考慮格式化字符串printf的問題,所以問題遠(yuǎn)沒有這么簡單。

 

Problem 9:符號無定義。
比如你用了TransmitFile,你就得加mswsock.lib(不過好像加的順序有講究的)
如果不知道加什么,就查sdk幫助和搜索,一般微軟會很熱心地注明這個API需要用那個lib去
鏈接。把所有l(wèi)ib加上去試也可以(只是這種方法有點(diǎn)菜)

 

Problem 10:MySQL UDF問題
比較通用的方法是寫個.def文件
LIBRARY "xxx"
EXPORTS
...
然后在工程中加入這個def
編譯好dll后拷貝到
C:\Program Files (x86)\MySQL\MySQL Server 5.1\lib\plugin
或者根據(jù)show variables like "plugin_dir";判斷插件位置
如果涉及別的dll,需要把依賴dll拷貝到PATH的路徑下,例如
C:\Program Files (x86)\MySQL\MySQL Server 5.1\bin
否則mysqld會因?yàn)槿狈ll而啟動不了UDF而認(rèn)為UDF不存在。
創(chuàng)建SQL類似于CREATE FUNCTION xxx RETURNS INT SONAME "xxx.dll";
安裝成功后select name, dl from mysql.func;查看
要調(diào)試UDF可以用fprintf(stderr,...)的方法,然后用mysqld --console來啟動mysqld。
另外最好用debug版測試,萬一崩潰了,mysqld會把輸出一些堆棧信息到控制臺上。

 

Problem 11: WSAStartup和memset問題

 

 

C代碼  收藏代碼
  1. #ifdef WIN32  
  2.  {  
  3.   WSADATA wsaData;  
  4.   if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {  
  5.    fprintf(stderr, "Socket Initialization Error. Program  aborted\n");  
  6.    return 0;  
  7.   }  
  8.  }  
  9. #endif  

 

 

這是windows的特有問題(寫linux網(wǎng)絡(luò)程序的人大概會很郁悶),
如果有一天發(fā)現(xiàn)getaddrinfo返回非零,
檢查一下main函數(shù)有沒有加WSAStartup。(連127.0.0.1都解析不了會很可笑)。
另外memset也是個需要注意的問題,例如初始化struct addrinfo變量hints需要
memset(&hints, 0, sizeof (hints));(有時候你忽略這個問題會出現(xiàn)一些古怪的結(jié)果)
然后給某個成員變量賦值。
linux的寫法就不會那么復(fù)雜,它用C99的寫法,在初始化時直接給變量的成員函數(shù)賦初始值。
順便一提VC支持字符串的全0初始,例如char s[10] = {0};比單純寫char s[10];要安全得多。

 

更正:

VC其實(shí)可以像gcc那樣給結(jié)構(gòu)體對象賦初值,只不過不是寫成 type a={.x = 10, };

而是寫成type a={a.x = 10,};所以沒必要用memset(低版本的VC則有必要?)

 

problem 12:缺少BSD套接字頭文件

在linux網(wǎng)絡(luò)編程中經(jīng)常會出現(xiàn)

#include <netinet/tcp.h>
#include <arpa/inet.h>

有時還會有

#include <sys/socket.h>

還有其他,如果只是使用BSD套接字,

問題是,mingw沒有(VC也是)。

但windows上的確存在BSD套接字API的子集,只不過需要包含的頭文件不是上面那些,而是

 

 

C代碼  收藏代碼
  1. #include <winsock2.h>  
  2. #include <ws2tcpip.h>  

 

 

如果對這個問題感興趣,可以參考這些資料:

 

* memcached1.2.6-win32移植的源代碼

http://code./memcached/

 

*PostgreSQL的源碼(\src\include\port\win32),對win32的移植

http://www./ftp/source/ 

 

(注:VC6似乎不行,待考)

 

problem 13:缺少sys/poll.h

win32沒有現(xiàn)成的機(jī)制實(shí)現(xiàn)poll(輪詢),也就是說:poll()不可移植

http://lists./mingw-users/msg05987.html

不過事實(shí)上有人給出poll()的非正式實(shí)現(xiàn):

 (未經(jīng)試驗(yàn),不過好像可以試試看)

* libmemcached

/poll/poll.c

https:///libmemcached/+download

-------------------------

(2010-09-10:補(bǔ)充drizzle,發(fā)現(xiàn)它的源代碼包中帶有poll.c,不知道是否可用)

* drizzle

https:///drizzle

-------------------------

如果你使用cygwin,這個問題可以忽略(因?yàn)槟J(rèn)是有poll.h和poll()的實(shí)現(xiàn))

(補(bǔ)充:

poll其實(shí)可以在msys的SDK中使用

msysDVLPR-1.0.0-alpha-1.tar.gz

但最終生成的exe導(dǎo)入了MSYS-1.0.DLL,而MSYS-1.0.DLL不可以單獨(dú)使用(依賴于msys)

如果只用于msys控制臺,可以嘗試用這個SDK(gcc version 2.95.3-1)

安裝教程:

http://www./wiki/HOWTO_Create_an_MSYS_Build_Environment

注意,它需要與msys目錄合并,不是放在/mingw目錄下

繼續(xù)補(bǔ)充:

poll其實(shí)有win32的port,參考

WSAPoll

http://msdn.microsoft.com/en-us/library/ms741669(VS.85).aspx

不過這個API僅用于Vista以上

 

problem 14: pthread-w32靜態(tài)庫造成程序崩潰的問題。

由于dll.c中dllmain()調(diào)用了這兩個API(定義在pthread.h)

PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);

如果pthread-w32被靜態(tài)鏈接到程序中,需要在main()函數(shù)開頭調(diào)用pthread_win32_process_attach_np初始化,否則程序會崩潰,且很難找到崩潰的原因(即使使用CDT調(diào)試)。

(2014/01/23補(bǔ)注:)代碼如下:(在main函數(shù)最開始的地方執(zhí)行)

C代碼  收藏代碼
  1. #ifdef __MINGW32__  
  2.     ptw32_processInitialize();  
  3.     //ptw32_processTerminate();  
  4. #endif  

 

 

 

problem 15: 關(guān)于VC6構(gòu)造函數(shù)的初始化表的問題。

不可以使用帶命名空間的基類。

例如class X:public std::Y{}

構(gòu)造函數(shù)X():std::Y(0),...{}是編譯出錯的,

需要繞圈,用typedef std::Y std_Y,然后再初始化:X():std_Y(0),...{}

 

problem 16:關(guān)于VC6的模板參數(shù)和嵌套問題。

有些時候,如果沒有用到模板參數(shù),那么template可以省略,

但對于VC6來說,省略template<class T>有時就偏偏不行。

VC6似乎不能把嵌套template成員函數(shù)單獨(dú)寫再類定義外部。

例如template<class T> template<class C>...

一種解決辦法是,放在類定義內(nèi)部。

 

problem 17:VC6在成員函數(shù)中調(diào)用基類方法可能會編譯失敗。

原因不明,不過用某些方法繞過這種編譯錯誤,例如使用未被覆蓋或重載的方法代替(廢話。。。)

 

problem 18: 使用winsock的API,在VC2008編譯時出現(xiàn)大量的錯誤:

1>c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(91) : warning C4005: “AF_IPX”: 宏重定義
1>        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(460) : 參見“AF_IPX”的前一個定義

一般是因?yàn)槌霈F(xiàn)這樣的包含

#include <windows.h>
#include <winsock2.h>

導(dǎo)致一堆宏重定義

使用宏WIN32_LEAN_AND_MEAN可以屏蔽之(應(yīng)該。。。)

用#define或者VC2008工程的預(yù)處理器設(shè)置均可。

 

problem 19: 線程局部變量的區(qū)別:

 

 

mingw32 does not support __thread (thread local storage).
but msvc support like it with _declspec(thread).
however mingw32 can ignore that.

 

參見:https://github.com/mattn/mod_perlite/commit/4f811433266d90d33568a5680c1499946a3bd897

20160926

可以參考這篇,引用自tbox/tboox:

線程局部存儲tls的使用

http:///cn/2016/09/28/thread-local/

寫道
gcc和clang的__thread修飾符
windows下msvc的__declspec(thread)修飾符
pthread庫pthread_setspecific和pthread_getspecific接口
windows下的TlsSetValue和TlsGetValue

 

 

problem 20:asprintf和vasprintf

-----------------------

注意,這里有個開源實(shí)現(xiàn)(未試驗(yàn))

http://www./software/snprintf/

-----------------------

出現(xiàn)在lua-checker的代碼中

http://code.google.com/p/lua-checker/

這兩個函數(shù)VC沒有,需要用特殊方法近似地模擬,一種方法是使用vsnprintf(低版本的VC可能沒有這個函數(shù))(20150808:VC6有個函數(shù)叫_vsnprintf,但沒有_vscprintf,也沒有對應(yīng)的_s版本)

 

C代碼  收藏代碼
  1. #ifdef _MSC_VER  
  2. #pragma warning(disable:4065)  
  3. #pragma warning(disable:4996)  
  4.   
  5. /* 
  6. 用malloc分配內(nèi)存,在程序結(jié)束后自動回收 
  7. see  
  8. http://pdfrecompressor./svn-history/r40/trunk/jbig2enc_modified/jbig2.cc 
  9. */  
  10. // -----------------------------------------------------------------------------  
  11. // Windows, sadly, lacks asprintf  
  12. // -----------------------------------------------------------------------------  
  13. #include <stdarg.h>  
  14. static int asprintf(char **strp, const char *fmt, ...)   
  15. {  
  16.     va_list va;  
  17.     va_start(va, fmt);  
  18.     const int required = vsnprintf(NULL, 0, fmt, va);  
  19.     char *const buffer = (char *) malloc(required + 1);  
  20.     const int ret = vsnprintf(buffer, required + 1, fmt, va);  
  21.     *strp = buffer;  
  22.     va_end(va);  
  23.     return ret;  
  24. }  
  25.   
  26. static int vasprintf(char **strp, const char *fmt, va_list va)  
  27. {  
  28.     const int required = vsnprintf(NULL, 0, fmt, va);  
  29.     char *const buffer = (char *) malloc(required + 1);  
  30.     const int ret = vsnprintf(buffer, required + 1, fmt, va);  
  31.     *strp = buffer;  
  32.     return ret;  
  33. }  
  34.   
  35. #endif  

 

另一種做法是使用臨時文件:

totem-plparser

https://github.com/zsx/totem-plparser

https://github.com/zsx/totem-plparser/blob/OAH/lib/asprintf.c

實(shí)現(xiàn)大概是這樣:

 

C代碼  收藏代碼
  1. #include "config.h"  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <stdarg.h>  
  5.   
  6. #ifdef _WIN32  
  7. #include <windows.h>  
  8. #endif  
  9.   
  10. int totem_private_asprintf(char **out, const char *fmt, ...)  
  11. {  
  12.     va_list ap;  
  13.     int ret_status = EOF;  
  14.     char dir_name[2001];  
  15.     char file_name[2000];  
  16.     FILE *fp = NULL;  
  17.     char *work = NULL;  
  18.   
  19.     va_start(ap, fmt);  
  20.   
  21.     /* Warning: tmpfile() does not work well on Windows (MinGW) 
  22.      *          if user does not have write access on the drive where  
  23.      *          working dir is? */  
  24. #ifdef _WIN32  
  25.     /* file_name = G_tempfile(); */  
  26.     GetTempPath ( 2000, dir_name );  
  27.     GetTempFileName ( dir_name, "asprintf", 0, file_name );  
  28.     fp = fopen ( file_name, "w+" );  
  29. #else  
  30.     fp = tmpfile();   
  31. #endif /* _WIN32 */  
  32.   
  33.     if ( fp ) {  
  34.         int count;  
  35.   
  36.         count = vfprintf(fp, fmt, ap);  
  37.         if (count >= 0) {  
  38.             work = calloc(count + 1, sizeof(char));  
  39.             if (work != NULL) {  
  40.                 rewind(fp);  
  41.                 ret_status = fread(work, sizeof(char), count, fp);  
  42.                 if (ret_status != count) {  
  43.                     ret_status = EOF;  
  44.                     free(work);  
  45.                     work = NULL;  
  46.                 }  
  47.             }  
  48.         }  
  49.         fclose(fp);  
  50. #ifdef _WIN32  
  51.         unlink ( file_name );  
  52. #endif /* _WIN32 */  
  53.     }  
  54.     va_end(ap);  
  55.     *out = work;  
  56.   
  57.     return ret_status;  
  58. }  

 

雖然麻煩,但在沒有vsnprintf時是個不錯的應(yīng)急方案。

重申一下,這只是近似的方案,并不一定和真正的asprintf功能一樣。

 

problem 21 獲取指定文件名(可能是相對路徑)的完整目錄名

和問題20一樣,出現(xiàn)在lua-checker的代碼中

http://code.google.com/p/lua-checker/

我的移植方案是用VC的C運(yùn)行時庫函數(shù)_fullpath和_splitpath來模擬dirname:

 

C代碼  收藏代碼
  1. #ifndef _MSC_VER  
  2. #include <libgen.h>           // For dirname()  
  3. #else  
  4.   
  5. #include <stdio.h>  
  6. #include <conio.h>  
  7. #include <stdlib.h>  
  8. #include <direct.h>  
  9.   
  10. static const char *dirname(const char *partialPath)  
  11. {  
  12.     static char full[1000] = {0};  
  13.     static char path_buffer[1000] = {0};  
  14.     static char drive[1000] = {0};  
  15.     static char dir[1000] = {0};  
  16.     static char fname[1000] = {0};  
  17.     static char ext[1000] = {0};  
  18.     static char fulldir[1000] = {0};  
  19.     if( _fullpath( full, partialPath, sizeof(full) ) != NULL )  
  20.     {  
  21.         _splitpath( full, drive, dir, fname, ext );  
  22.         strcpy(fulldir, drive);  
  23.         strcat(fulldir, dir);  
  24.     }  
  25.     else  
  26.     {  
  27.         strcpy(fulldir, "");  
  28.     }  
  29.     return fulldir;  
  30. }  
  31. #endif  

 

problem 22 只能讀文件4KB以內(nèi)的內(nèi)容?

使用fopen的"r"模式,一次性讀取4KB內(nèi)容到char[](使用fread函數(shù)),發(fā)現(xiàn)4KB以外的內(nèi)容都是0(沒有完整地讀出)。

正確的做法是使用"rb“模式。

 

problem 23 VC2008的char類型的無符號問題

因?yàn)閏har在舊版的C中充當(dāng)BYTE類型來使用(unsigned char),但新版的VC2008實(shí)施強(qiáng)類型,char類型將被當(dāng)作有符號數(shù)來處理,如果想把char當(dāng)作無符號來使用,應(yīng)該更改VC工程的屬性,添加/J參數(shù)。

 

problem 24 long long 輸出

 

C代碼  收藏代碼
  1. #include <stdio.h>     
  2.                     
  3. int main(void)  
  4. {     
  5.     long long mem = 123456789012;     
  6.     printf("mem=%ld\n",mem);     
  7.     exit(0);     
  8. }     
  9. //輸出不正確呀,應(yīng)該用什么轉(zhuǎn)移符?  
  10.   
  11. print("mem=%lld\n",men);   

 

see http://blog.csdn.net/huangxb_csu/archive/2008/12/30/3648779.aspx

 

 

problem 25: 找不到strcasecmp

摘自

http://blog.csdn.net/chinacodec/archive/2010/01/03/5124977.aspx

 

C代碼  收藏代碼
  1. #ifdef _MSC_VER  
  2. #include <string.h>  
  3. #define strcasecmp stricmp  
  4. #define strncasecmp  strnicmp  
  5. #endif  

 

problem 26 : 使用SDL頭文件時出現(xiàn)undefined reference to `WinMain@16' 

原因是SDL.h把main宏定義了,可以用nm或dumpbin檢查.o文件的符號是否有_main(可以用grep過濾)

解決辦法可以取消main的宏定義:

 

C代碼  收藏代碼
  1. #undef main  
  2. int main( int argc, char* argv[] ) {  

補(bǔ)注: 正確做法應(yīng)該是使用libSDLmain.a的WinMain入口,方法是把鏈接參數(shù)中的-lmingw32提前到-lSDLmain之前,例如

寫道
-lmingw32 -lSDLmain -lSDL

 

 

 

 

problem 27: drand48和srand48

Windows上可以簡單地實(shí)現(xiàn)

 

C代碼  收藏代碼
  1. #ifdef _WIN32  
  2. #define drand48() (((float) rand())/((float) RAND_MAX))  
  3. #define srand48(x) (srand((x)))  
  4. #endif  

 或參考http://blog.csdn.net/jimmyblind/archive/2010/05/02/5550042.aspx

注意,對隨機(jī)數(shù)取模是個不好的設(shè)計(jì),因?yàn)槿∧5玫叫蛄械目赡懿粔蚓鶆颉?/p>

 

 

problem 28: bcb6的“Call to function 'xxx' with no prototype”警告

對于空參數(shù)表的函數(shù)聲明,必須指明為void,例如xxx(void);

 

(后續(xù),待修改)

 

problem 29: 在Windows上使用MinGW+SWIG書寫JNI

Windows上的JNI實(shí)際上是Java虛擬機(jī)調(diào)用原生dll的導(dǎo)出函數(shù)。

嘗試使用Cygwin+SWIG生成JNI,但不成功(提示aborted)

但使用mingw則沒有問題(可能是cygwin的dll造成JNI不可用)

需要注意的是最后編譯dll時使用的參數(shù)-Wl,--add-stdcall-alias,見

http://www./tutorial.html

 

我嘗試用手工Makefile編譯JNI,編譯工程是官方發(fā)布包中的swigwin-2.0.3\Examples\java\simple

方法如下:

 

1. 創(chuàng)建目錄swigtest,把simple示例的代碼都復(fù)制進(jìn)去

 

2. 把jdk下的include文件(我的JDK頭文件在

D:\java\jdk1.6.0_20\include

D:\java\jdk1.6.0_20\include\win32

)全部復(fù)制到目錄swigtest(include\win32下的文件直接和include下的頭文件放在一起)

這樣做是因?yàn)?,我在使?I時無法指向這兩個目錄(原因不明)

 

3. 手工書寫新的Makefile

(注意,我的javac在d:\java\jdk1.6.0_20\bin\javac.exe,所以指向mingw風(fēng)格的目錄/d/java/jdk1.6.0_20/bin/javac)

 

 

Makefile代碼  收藏代碼
  1. CC := gcc  
  2. LD := ld  
  3. RM := rm -f  
  4. SWIG := swig  
  5. OBJS := example.o example_wrap.o  
  6. CFLAGS := -I.  
  7. # -I/D/java/jdk1.6.0_20/include -I/D/java/jdk1.6.0_20/include/win32  
  8. # -I/cygdrive/d/java/jdk1.6.0_20/include   
  9.   
  10. JAVAC := /d/java/jdk1.6.0_20/bin/javac  
  11.   
  12.   
  13. all : example.dll java  
  14.   
  15. java :   
  16.     ${JAVAC} *.java  
  17.   
  18. example.dll : ${OBJS}  
  19.     ${CC} -shared ${CFLAGS} -Wl,--add-stdcall-alias -o $@ ${OBJS}  
  20.   
  21. # -mno-cygwin   
  22.   
  23. %.o : %.c  
  24.     ${CC} ${CFLAGS} -o $@ -c $<  
  25.       
  26. # exampleJNI.java  
  27. example_wrap.c : example.i  
  28.     ${SWIG} -o $@ -java $<  
  29.   
  30. clean :  
  31.     ${RM} *.o *.class *.dll example.java example_wrap.c exampleJNI.java  

 

然后運(yùn)行:

> make clean all

> java runme

 

(補(bǔ)充說明:如果要編譯64位的JNI動態(tài)庫(因?yàn)?4位JRE只能使用64位的dll動態(tài)庫),需要使用-m64或-B參數(shù)生成64位dll,或者用TDM-GCC-64工具鏈(默認(rèn)生成64位exe和dll))

 

 

problem 30 編譯動態(tài)庫和靜態(tài)庫

動態(tài)庫:

gcc -shared -o <.dll文件> <.o文件>...

 

靜態(tài)庫:

ar rcs <.a文件> <.o文件> ...

(有時下面還可以對.a文件使用ranlib命令,但一般可以忽略不做)

 

 

problem 31  configure時輸出.i文件檢查宏展開后的編譯錯誤

 

 

CFLAGS=-save-temps

 

see

http://code.google.com/p/memcached/issues/detail?id=111

 

problem 32  isspace錯誤

 

如果在cygwin中使用不經(jīng)過類型轉(zhuǎn)換的isspace
array subscript has type ‘char’

 

解決辦法如下 

 

/* Avoid warnings on solaris, where isspace() is an index into an array, and gcc uses signed chars */
#define xisspace(c) isspace((unsigned char)c)

 

或者手工轉(zhuǎn)換類型 

 

see

https://github.com/lindner/memcached/blob/master/util.c

http://code.google.com/p/memcached/issues/detail?id=111

 

類似的情況出現(xiàn)在cygwin的大部分isXXX函數(shù)

 

 

problem 33 printf系輸出的亂碼問題

 

 

C 使用wprintf,_tprintf 打印簡體中文的方法 【Locale.h】

http://www.cnblogs.com/niuniu502/archive/2009/02/17/1392636.html

 

需要分兩種情況考慮:

1. 非Unicode版

_ftprintf(stderr, _T("%S\n"), "你好嗎");

2. Unicode版

#include <locale.h>

setlocale(LC_ALL, "");

_ftprintf(stderr, _T("%s\n"), _T("你好嗎"));

 

注意,兩種情況的%s的大小寫含義是不一樣的!

這一點(diǎn)在微軟的文檔中有詳細(xì)說明——

就是說printf的%s是非Unicode字符串的占位符;

而wprintf的%s是Unicode字符串的占位符;

printf的%S是Unicode字符串的占位符;

而wprintf的%S是非Unicode字符串的占位符;

wprintf還需要setlocale才能正常在控制臺中輸出。

 

另外,出現(xiàn)亂碼還可能是因?yàn)椤獏?shù)個數(shù)不匹配

problem 34 VC6與MinGW的內(nèi)聯(lián)匯編。
有時需要在C中嵌入?yún)R編以獲取底層硬件信息。
例如在mingw中測試CPU頻率
C代碼  收藏代碼
  1. static long CPUClock __asm__("CPUClock") = 0;  
  2.   
  3. ...  
  4.   
  5.   
  6.         asm (  
  7.             ".intel_syntax noprefix\n\t"  
  8.             "RDTSC\n\t"  
  9.             "MOV        [CPUClock],     EAX\n\t"  
  10.             ".att_syntax\n"  
  11.         );  
  12.         Sleep(1000);  
  13.         asm (  
  14.             ".intel_syntax noprefix\n\t"  
  15.             "RDTSC\n\t"  
  16.             "SUB        EAX,            [CPUClock]\n\t"  
  17.             "MOV        [CPUClock],     EAX\n\t"  
  18.             ".att_syntax\n"  
  19.         );  
  20.         CPUClock /= 1000000;  
限制是,
1) 可以嵌入C變量,但不能與寄存器的名稱有沖突(2014/01/23注:__asm__后面的引號中的匯編名稱必須為大寫,否則可能編譯出錯)
2) 默認(rèn)不是intel格式,所以開頭要用宏指令聲明為intel語法。
大部分情況下最好用GNU風(fēng)格的匯編,
但有時需要移植Win32的匯編時可以考慮寫成上面不倫不類的樣子。
對應(yīng)的vc6內(nèi)嵌匯編是:
see also:
C代碼  收藏代碼
  1. __asm  
  2. {  
  3.     RDTSC  
  4.     MOV     [CPUClock],     EAX  
  5. }  
  6.   
  7. Sleep( 1000 );  
  8.   
  9. __asm  
  10. {  
  11.     RDTSC  
  12.     SUB     EAX,            [CPUClock]  
  13.     MOV     [CPUClock],     EAX  
  14. }  
  15.   
  16. CPUClock /= 1000000;  
在VC6中匯編內(nèi)嵌的C變量只要聲明為函數(shù)的局部變量即可。
C代碼  收藏代碼
  1. long CPUClock       = 0;  
problem 35: Win32程序中轉(zhuǎn)至發(fā)布版時出現(xiàn)控件不能顯示的情況。
那是因?yàn)槭褂肅reateWindowEx這類函數(shù)創(chuàng)建控件時返回0。
原因是編譯時出現(xiàn)警告:
LINK : warning LNK4089: all references to "comdlg32.dll" discarded by /OPT:REF
而控件類的創(chuàng)建是在comdlg32.dll中進(jìn)行,忽略它將導(dǎo)致控件類不加載,引發(fā)錯誤。
解決辦法是調(diào)用InitCommonControls(需要增加鏈接comctl32.lib)
同樣原因,在使用RichEdit20A前要LoadLibrary("RICHED20.DLL")
problem 36: mingw gcc 4需要動態(tài)鏈接libgcc_s_dw2-1.dll
懷疑mingw的開發(fā)者想加入一些全局的功能(?),例如strace。
解決辦法是在gcc后面使用-static-libgcc編譯開關(guān)。
如果用TDM-GCC則沒有此問題。
轉(zhuǎn)自:
MinGW升級到4.5.2生成的exe需要libgcc_s_dw2-1.dll和libstdc++-6.dll ? 寫道
-static-libgcc在 gcc/g++ 或 ld 中加上這個參數(shù), 就可以不用 libgcc_s_dw2-1.dll
-static-libstdc++在 g++ 或 ld 中加上這個參數(shù), 就可以不用 libstdc++-6.dll
-static在 gcc/g++ 或 ld 中加上這個參數(shù), 對所有的庫都會采用靜態(tài)鏈接的方式

problem 37: 如何修改CMakeLists.txt,使生成的VC工程可以鏈接C運(yùn)行時庫的多線程靜態(tài)版(把/MD換為/MT)
例如,llvm-2.7的源碼中的CMakeLists.txt有一個對MSVC的判斷:
if( MSVC )
  # List of valid CRTs for MSVC
  set(MSVC_CRT
    MD
    MDd)
  set(LLVM_USE_CRT "" CACHE STRING "Specify VC++ CRT to use for debug/release configurations.")
  add_llvm_definitions( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS )
  add_llvm_definitions( -D_SCL_SECURE_NO_WARNINGS -DCRT_NONSTDC_NO_WARNINGS )
  add_llvm_definitions( -D_SCL_SECURE_NO_DEPRECATE )
  add_llvm_definitions( -wd4146 -wd4503 -wd4996 -wd4800 -wd4244 -wd4624 )
  add_llvm_definitions( -wd4355 -wd4715 -wd4180 -wd4345 -wd4224 )
  # Suppress 'new behavior: elements of array 'array' will be default initialized'
  add_llvm_definitions( -wd4351 )
  if (NOT ${LLVM_USE_CRT} STREQUAL "")
    list(FIND MSVC_CRT ${LLVM_USE_CRT} idx)
    if (idx LESS 0)
      message(FATAL_ERROR "Invalid value for LLVM_USE_CRT: ${LLVM_USE_CRT}. Valid options are one of: ${MSVC_CRT}")
    endif (idx LESS 0)
    add_llvm_definitions("/${LLVM_USE_CRT}")
    message(STATUS "Using VC++ CRT: ${LLVM_USE_CRT}")
  endif (NOT ${LLVM_USE_CRT} STREQUAL "")
后面加上這樣的句子:
foreach(flag_var
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
   if(${flag_var} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
   endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
這里使用了regex replace把所有flags的/MD替換為/MT。
problem 38: strdup or _strdup ?
see
如果在Windows下,建議用_strdup,
如果在Linux下,建議用strdup。
實(shí)際上這個函數(shù)不是太好,建議最好別用。
20160707:如果提示沒有定義,可以用這個函數(shù)替換:
char *my_strdup(const char *str) {
    size_t len = strlen(str);
    char *x = (char *)malloc(len+1); /* 1 for the null terminator */
    if(!x) return NULL; /* malloc could not allocate memory */
    memcpy(x,str,len+1); /* copy the string into the new buffer */
    return x;
}
參考:http:///questions/5573775/strdup-error-on-g-with-c0x
problem 39: ISO 'for'內(nèi)的局部變量
例如在for(int i=1; i < 10; i++)這樣的循環(huán)外繼續(xù)使用變量i會導(dǎo)致cygwin警告
提示添加-fpermissive
所以最好把int i移到循環(huán)之前,以兼容不同的編譯器。
problem 40: cygwin用new創(chuàng)建變長的字符串可能未初始化為0
char *buffer = new char[size + 1];
buffer[size] = 0;
最后一句是確保末尾的0(只有Cygwin有必要)
VC6和Linux可以不寫最后那句buffer[size] = 0;,
是因?yàn)閚ew已確保整個數(shù)組內(nèi)容已清零。
problem 41: VC6編譯時出現(xiàn)internal heap limit reached; use /Zm to specify a higher limit
原因是代碼中出現(xiàn)很大的常量數(shù)組時:解決辦法是在工程右鍵->Settings->C/C++下方添加/Zm1500
MinGW沒有此問題,但編譯時較慢。
problem 42: 使用g++編譯c++代碼時無法使用stricmp
解決方法:C++不使用stricmp,而是使用strcasecmp(#include <cstring>),
see
problem 43: 
為什么vc2008編譯就提示找不到msvcr90d.dll
方法:
* 關(guān)閉增量鏈接(配置屬性->鏈接器->常規(guī))
或者:
* Project Properties -> Manifest Tool-> Use FAT32 Work-around 為Yes重新編譯
參考自:http://bbs.csdn.net/topics/220055015

 problem 44:

getopt和getopt_long重入問題。

一般程序只能調(diào)用一次getopt或getopt_long,如果第二次調(diào)用,將無法獲取參數(shù)信息。

解決辦法是在調(diào)用之前對optreset和optind賦值為1(這兩個變量聲明在getopt.h中)

  optreset = 1;

  optind = 1;

 

 

problem 45:

fwrite返回值判斷出錯問題和原因

//代碼只是大概意思,可能有誤,僅參考用

if (fwrite(buffer, sizeof(unsigned char), nRead, file) != (size_t)(nRead)) {

   fprintf(stderr, "error : %s .\n", strerror(errno));

}

如果出現(xiàn)不等于的情況(fwrite出錯),與socket(網(wǎng)絡(luò)套接字)的寫入不同的是,不是因?yàn)閷懭霐?shù)據(jù)不全,而是因?yàn)槠渌颍ɡ?,從strerror可以知道,因?yàn)榇疟P空間不足),不要主觀臆斷。

另外,nRead似乎有范圍限制(受限于size_t的大?。?span style="color: #333333; font-family: Arial, 'Microsoft YaHei'; line-height: 23px;">注:理論上32位的最大值是2GB,但實(shí)際讀入和寫出的最大值跟fread和fwrite實(shí)現(xiàn)有關(guān),參考http:///questions/18879410/fread-number-of-bytes-limit

http:///questions/730709/2gb-limit-on-file-size-when-using-fwrite-in-c

))

 

problem 46:

如果在模板參數(shù)中引用std標(biāo)準(zhǔn)庫內(nèi)的類型,必須加typename,否則編譯可能會出錯。

例如:假設(shè)vectorEx類繼承std::vector,則

Cpp代碼  收藏代碼
  1. template<class T> bool vectorEx<T>::erase(T t) {  
  2.     iterator it = begin();  

 

 要改寫成:

 

Cpp代碼  收藏代碼
  1. template<class T> bool vectorEx<T>::erase(T t) {  
  2.     typedef typename vectorEx<T>::iterator iterator;  
  3.     iterator it = vector<T>::begin();  

 

 而類內(nèi)部的聲明

Cpp代碼  收藏代碼
  1. pair<iterator, bool> insert(T t);  

 

 (可能)需要改寫成(否則iterator可能會報找不到定義的編譯錯誤,

相當(dāng)于寫成

std::pair<typename vectorEx<T>::iterator, bool> insert(T t)

注意typename的位置:

 

Cpp代碼  收藏代碼
  1. typedef typename vectorEx<T>::iterator iterator;  
  2. typedef typename vectorEx<T>::const_iterator const_iterator;  
  3. typedef typename vectorEx<T>::size_type size_type;  
  4. pair<iterator, bool> insert(T t);  

 

 

problem 47:鏈接exe時出現(xiàn)下劃線符號強(qiáng)制鏈接成@符號

寫道
Warning: resolving _Sleep by linking to _Sleep@4
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups

這個警告雖然會成功生成exe文件,但程序可能會崩潰。那是因?yàn)榫幾g器不知道windows api函數(shù)Sleep是stdcall函數(shù)而非普通c函數(shù),最好確保添加頭文件以消除這個警告

 

C代碼  收藏代碼
  1. #define WIN32_LEAN_AND_MEAN  
  2. #include <windows.h>  

 

(2014/08/16)

 problem 48. -mthreads與mingwm10.dll

http://tkamogashira.users./sodan/tips/mingwcross.html

(20140912)

簡單來說,如果使用-mthreads編譯程序,就不能完全靜態(tài)編譯(需要動態(tài)鏈接mingwm10.dll)以保證多線程下的異常處理是正常的(好像還是因?yàn)榧嫒菖f版本W(wǎng)indows,所以可以認(rèn)為是mingw一個不完美的bug)。

這個問題出現(xiàn)在靜態(tài)編譯qt 4.3.5的時候(在configure的時候關(guān)閉C++異常機(jī)制可以避免鏈接mingwm10.dll)

一般的程序不使用C++異?;蛘卟皇褂?mthreads就不會遇到這個問題。

 

20141216:

problem 49:unresolved external symbol __iob

參考:

http://blog.sina.com.cn/s/blog_5d890d070100fpj1.html

 

寫道
1、缺少libc.lib
解決這個問題的方法是去掉鏈接到libc.lib,具體地點(diǎn):項(xiàng)目-〉屬性-〉配置屬性-〉鏈接器-〉忽略特定庫。
2、unresolved external symbol __iob
這個__iob找不到的問題費(fèi) 了我大部分的時間。跟蹤到stdio.h文件,發(fā)現(xiàn)那里有個關(guān)于iob的宏,終于搞定。加入一句話到.cpp文件中:extern "C" { FILE _iob[3] = {__iob_func()[0], __iob_func()[1], __iob_func()[2]}; }

 

20141227:

problem 50:匿名結(jié)構(gòu)體

如果匿名結(jié)構(gòu)體的形式是(非標(biāo)準(zhǔn)寫法)

C代碼  收藏代碼
  1. struct B{  
  2.     struct A; //注意,這里不是指針變量也不是結(jié)構(gòu)體變量,而是結(jié)構(gòu)體類型名(假設(shè)已聲明過)  
  3.     int b;  
  4. };  

 等效于(下面是gcc標(biāo)準(zhǔn)寫法)

 

C代碼  收藏代碼
  1. struct B{  
  2.     struct A{  
  3.         int a;  
  4.     }; //gcc寫法,不能用于VC++  
  5.     int b;  
  6. };  

 

gcc需要在gcc后添加編譯參數(shù)-fms-extensions

visual studio需要添加/wd4201 /wd4996參數(shù)

C4201: nameless struct/union,

C4996: This function or variable may be unsafe.

這樣做是兼容微軟的匿名結(jié)構(gòu)體語法

C代碼  收藏代碼
  1. struct A{  
  2.     int a;  
  3. };  
  4. struct B{  
  5.     struct A; //VC++寫法,可以用于gcc,但需要設(shè)置編譯器參數(shù)  
  6.     int b;  
  7. };  

    匿名結(jié)構(gòu)體的作用是允許struct B在指針取成員的語法上擁有struct A的所有成員(前提是不能有相同名字的其他成員),同時struct B*可以安全地強(qiáng)制轉(zhuǎn)換成struct A*,實(shí)現(xiàn)類似C++的繼承特性。

    還有類似的做法是struct B擁有struct A*(是指針而非結(jié)構(gòu)體),不過匿名結(jié)構(gòu)體的好處是內(nèi)存分配只需要做一次 。

詳細(xì)請參考:

https://github.com/teejii88/mgui

http://pingf./categories/4252/posts

 

 

 

20150808:

problem 51:字節(jié)對齊寫法

(參考mruby)

 

(1)gcc寫法和vc寫法(不含VC6),注意是作為變量修飾符使用

const uint8_t

#if defined __GNUC__

__attribute__((aligned(4)))

#elif defined _MSC_VER

__declspec(align(4))

#endif

k[] = {...}

 

(2)VC6寫法(注意,不是修飾符,是pragma命令)

#ifdef _MSC_VER

#pragma pack(push)

#pragma pack(4)

#endif

...

 

#ifdef _MSC_VER

#pragma pack(pop)

#endif

 

 

(20160311)

problem 52.error: '::swprintf' has not been declared的解決

http://blog.sina.com.cn/s/blog_4f183d9601015zls.html

解決辦法:-U__STRICT_ANSI__

 

(20161008)

__builtin_函數(shù)在某些版本的mingw中不存在,例如__builtin_unreachable(參考:jerryscript)

Emulating GCC's __builtin_unreachable?

http:///questions/6031819/emulating-gccs-builtin-unreachable

GCC內(nèi)建函數(shù)

https://gcc./onlinedocs/gcc/Other-Builtins.html

 

 (20170222)

獲取宏定義(隨便創(chuàng)建一個c文件然后傳入?yún)?shù)-E -dM)

 gcc -E -dM test.cpp | grep MINGW

參考:(原文是gcc -posix -E -dM - </dev/null)

http://blog.csdn.net/cywosp/article/details/10730931

 

 (20170315)

還有一種辦法是強(qiáng)制加入頭文件 -include cstddef或者修改源代碼:include<cstddef>或using std::ptrdiff_t // ptrdiff_t does not name a type造成編譯錯誤 - klarclm的專欄 - 博客頻道 - CSDN.NET

http://blog.csdn.net/klarclm/article/details/8565484

 

修改:

2016-03-11 添加problem 52

2015-08-08 添加problem 51

2014-12-27 添加problem 50

2014-12-16 添加problem 49

2014-01-28 修改problem 26

2014-01-23 添加problem 46、47

2013-05-30 添加problem 45

2013-05-25 添加problem 44

2013-04-18 添加problem 43

2012-07-04 添加problem 41, 42

2011-12-25 添加problem 38, 39, 40

2011-12-02 添加problem 37

2011-11-21 添加problem 36

2011-11-19 添加problem 35

2011-11-10 添加problem 34

2011-07-27 修改problem 20

2011-07-14 添加problem 33

2011-05-01 添加problem 31、32

2011-04-29 增加problem 29、30

2011-04-25 增加開頭的參考鏈接

2011-04-23 補(bǔ)充problem 28

2011-04-10 補(bǔ)充problem 25、26、27

2011-03-27 補(bǔ)充problem 24

2011-02-01 補(bǔ)充problem 22、23

2011-01-25 補(bǔ)充problem 20、21

2010-12-21 補(bǔ)充problem 19

2010-12-07 補(bǔ)注WSAPoll的問題

2010-11-01 補(bǔ)充problem 18

2010-10-31 補(bǔ)充problem13:WSAPoll

2010-09-23 補(bǔ)充problem 15,16,17.來自于mysql++編譯的移植問題。

2010-09-08 補(bǔ)充problem13中關(guān)于drizzle源碼包中的poll實(shí)現(xiàn)

2010-09-01 補(bǔ)充problem13使用msysDVLPR的情況

2010-08-28 增加problem12, 13, 14

2010-08-14 修改了problem11,補(bǔ)充了problem7和problem5

 

 

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多