我们的研发人员经常会编译不同版本的产品,因此TSINGSEE青犀视频云边端架构中的很多产品都有不同版本。

我们的研发人员近期用vs2010编译EasyPlayerPro-Win、EasyPlayer-RTMP-Win、EasyPlayer-RTSP-Win、EasyRTMP、EasyRTMPClient和EasyStreamClient等项目时,出现了缺失msvcp100(d).dll和msvcr100(d).dll库文件的报错。

我们先来复现下问题:

1)首先把编译的exe文件放到虚拟机上运行, 2)利用Everything软件找到文件缺失库(msvcp100(d).dll和msvcr100(d).dll), 3)随后为了处理这一问题,我们把库文件放到指定目录打开程序,但同样也会出现无法正常启动的报错,错误码为0xc000007b。

“应用程序无法正确启动”,错误代码0xc000007b是一个视窗操作系统错误,通常在将系统升级到新版本后通常会发生。虽然它已经在早期的视窗版本(7,8和8.1)上注册,但受此错误影响的绝大多数PC都运行Windows 10。

由于这种报错我们一般无法直接确定出问题的数据库具体需要替换为哪一个,因此可以利用Everything软件找下个缺失库,把之前放的msvcp100(d).dll和msvcr100(d).dll给重新替换。比如在本文我们就用到了msvcp100.dll、msvcp100d.dll、msvcr100.dll和msvcr100d.dll这四个数据库,重新打开exe文件,不再提示错误。

注:本文使用的数据库跟编译程序有关,不同程序数据库不同,此处仅供参考。

我把vc6.0上运行没有问题的代码挪到vs2010上,出现了一系列问题。 其根本原因是两种编译器默认编码不一样,vc6.0中默认的编码是(多字节)Ascii编码,VS2010中默认的编码是Unicode编码。

可以简单粗暴地改回去 打开菜单栏–>项目–>XXX属性–>配置属性–>常规–>字符集–>设置回Ascii编码

编译没有问题。

看了一下两种编码的区别:

ANSI 在不同的操作系统下代表着不同的编码。在我们正常用的简体中文windows操作系统中,ANSI代表着GBK编码,而在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。

UNICODE是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

作者:米奇小林 CString与char*互转及ANSI 和 UNICODE 编码 https://www.sxzhongrui.com/p/9804c28e21e8 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

那么,什么是字符集? 规定二进制数据和某种语言内的文字之间的对应关系,这就叫该种语言的字符集 最基本的是ASCII,规定数值48对应字符’0’,诸如此类,但由于这种对应关系的历史局限性(发明它的人当时没兴趣考虑非英文语言),同样的二进制数据,在不同的字符集内就对应不同的文字 而规定一套对应关系,使得二进制数据能够对应很多语言的文字,这就叫Unicode

使用Unicode编码显然更好。

所以我最后还是改回去了。

第一个问题是

error C2664: ‘strtol’ : cannot convert parameter 1 from ‘CString’ to ‘const char *’

不能将参数 1 从“CString”转换为“const char *”;

text=strtol(m_recieve,NULL,16);

//其中text为long型,m_recieve为CString型。

strtol函数的功能是转换字符串为长整形数字。 上面那句代码的意思是:把m_recieve这个字符串转换成16进制数并赋值给text。

但是在Unicode编码下出错了,因为在这个long strtol(const char *nptr,char **endptr,int base);函数中变量的字符串类型是const char,而Unicode编码下的字符串类型是const wchar_t。

所以要改成text=wcstol(m_recieve,NULL,16);

//关于这两个函数:

long wcstol(const wchar_t *nptr,wchar_t **endptr,int base);

long strtol(const char *nptr,char **endptr,int base);

参数:

1、nptr,需要转换的以’\0’作为终止符的字符串指针

2、endptr,如果有,则转换到该指针位置就停止

3、base,转换中如果遇到大于或等于base的字符就停止,一般设置为10

注意:

1、如果超出long上线,返回LONG_MAX或LONG_MIN

2、如果无法解析,返回0

第二个问题是:

error C2593: ‘operator =’ is ambiguous 不明确

定义了一个CString 对象m_strInputLine 在消息处理函数中:

void CTextView::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)

{

m_strInputLine += nChar;

}

问题在于 CString,在vs2010中,为unicode,wchar_t基类型。 而CString,在vc6.0中为ansi,char基类型。 所以上述代码中的m_strInputLine是wchar_t,而定义的时候nchar是无符号整型。 所以我们必须强制类型转换,将UINT nChar转换成wchar_t。

pDoc->StringData += nChar; 编译时出现“operator +=”不明确

改正方法:

pDoc->StringData+=(char)nChar,因为系统里面存在一个wchar_t的类型,所以如果支持了这个类型的话,从unsigned nt转换到wchar_t和char的等级都是标准转换,所以编译器无法判断到底应该转换到哪一个,故而导致了这个问题。

m_space=m_space+" ";

把char型改为wchar_t类型:

m_space=m_space+(wchar_t)" "

第三个问题是:

【error】LINK1123: failure during conversion to COFF: file invalid or corrupt

意思是由于COFF标识转换失败。而在连接中完成此项工作的是cvtres.exe。这个错误的原因是存在多个版本的cvtres.exe。

所以找到这个文件删掉就好了

第四个问题是:

error C1189: #error : Please use the /MD switch for _AFXDLL builds

解决方法:

修改设置:工程(Project)-> 属性(Properties)-> 配置属性(Configuration Properties)-> c/c+±> 代码生成(Code Generation)->运行库(Use run-time library)->多线程调试DLL(/MD) //百度了一下那几个选项什么意思:

多线程DLL(/MD):在dll中使用多线程,创建动态链接库的release版本,需要选择。 多线程(/MT): 在exe里使用多线程,创建exe的release版本,需要选择。 多线程调试(/MTd):同/MT一样,不过是在Debug版本中使用。 多线程dll调试(/MDL):同/MD一样,不过是在Debug版本中使用。

第五个问题是在编译已经没有error,运行的时候弹出来的提示:

Run-Time Check Failure #2 - Stack around the variable “XX” was corrupte

中文翻译就是“在变量XX周围的堆栈已损坏”。 意思是在我们的程序中,在某个变量附近的内存被破坏了,如果出现此类问题,一般表示我们的程序存在内存越界。MSDN的解释是在堆栈外面读写某数据。

最后我是把“project->配置属性->c/c+±>代码生成->基本运行时检查 设置为默认值,就没有这样的错误了。

我觉得还是两种编码转换的原因使得数据变大了,但是我看不出来:

CString,在vs2010中,为unicode,wchar_t基类型。 而CString,在vc6.0中为ansi,char基类型。

所以看了一下wchar_t和char的区别:

对于ascii码的char事实上就是unicode码wchar的首个字节码。

窄字符char就是8bit表示的byte,长度固定。char字符只能表示ASII码表中的256个字符,包括前128个可见字符和后面的128个不可见字符。

而wchar_t则是因为char所能表示的字符数太少(256个)而应运而生的,它的长度可以8bit,16bit,32bit,长度是与不同平台上的c库相关的。其实这个长度是根据指定平台上想要用的encoding编码方式来设定的。

char可以用来指向各种数据的内存,不是因为它们都是char字符数据,而是因为char的大小是1个字节,方便指针控制(如果你要用void指向各种内存,概念上是更加正确了,你试试看怎么偏移指针)

wchar_t其实就是typedef的2字节short,也就是对应unicode的编码范围为2字节数据,用的就是这种数据类型的字节数而已

所以char和wchar_t指向同一段内存,有什么错?一点错误都没有,它们都只指向这一段二进制数据而已,区别就在于你使用这两种类型的指针来操作数据的时候,按照相应的类型来操作这段内存,仅此而已。

应该就是char变成wchar_t导致的error吧,有人知道怎么改吗?

最后一个问题就是我运行程序的时候显示出乱码“00?FC?80?92?80?82?80?81?EE?FF?”和“12歠02歠00歠01歠6E歠01歠70歠00歜”或者“12歠02歠00歠01歠6E歠01歠70歠00\”

我真是绝望了。。。 最后莫名其妙地从 改成 最后改成这样终于好了

我还是不太懂这种字符串的转换,有空再找书仔仔细细地看吧…

最后马克一下我觉得非常有用的tips,虽然他的主人写的不明不白的: 原地址:https://www.sxzhongrui.com/judes/p/6146795.html

unicode下数据之间的转换 首先mfc下字符串只有两种数据:char(一个字节)和wchar_t(两个字节),很多其他数据类型如TCHAR,WCHAR等都是这个两个基本类型的宏定义,BYTE是uchar

1、对话框打印char*

char* info="";

::MessageBoxA(this->m_hWnd, info, “”, MB_OK);

2、CString转char*

int nLen; char * wsabuf = NULL; USES_CONVERSION; wsabuf = W2A(send_txt_str);//send_txt_str为CString消息

3、char*转CString

直接强制转换

4、_T(“AA”)转0xAA

BYTE byte1 = wcstol(_T(“AA”), NULL, 16);

5、_T(“你好”)转C4 E3 BA C3

用2的方法转char*->BYTE*,定义一个循环,在循环中定义一个临时CString变量Format取出单个BYTE元素

6、字符串转整数,“ff”、_T(“ff”)转256

用atoi那一系列函数(a代表ascii,to代表转化,i代表int)

同上还有itoa一系列函数

ttoi(),CString转整数

使用strtol系列函数:(str to long)

int a;

CString str;

str=_(“1234”);

a=wcstol(str,NULL,10);

a->1234

7、_T(“01FF”)转十进制:511

long a = wcstol(_T(“01FF”),NULL,16);//a=511

8、整数转字符串

_ltoa

9、把整数的十六进制转化成CString int a=20; CString temp_str; temp_str.Format(_T("%02x"),20); 10、C4 E3 BA C3转_T(“你好”) 强制转换(CString)

我的输出结果和目标输出结果,一模一样但是无法被识别。查了半天错,发现是编码格式不一样,vs2010默认的编码格式是Unicode,而目标格式是ansi。改过来就好了。

打开菜单栏–>项目–>XXX属性–>配置属性–>常规–>字符集–>设置你想要的编码方式即可