初次使用VS2010基于C++开发项目碰到的问题及解决方法

折月煮酒 提交于 2019-12-06 01:44:44

1、将过去的工程用VS2010打开的时候。你有可能会遇到一大堆的警告:warning C4996。 
比如:warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 
原因是Visual C++ 2005使用了更加安全的run-time library routines。 
新的Security CRT functions(就是那些带有“_s”后缀的函数): 
http://msdn2.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx 
那么如何搞定这些警告呢:

原因解释
这种微软的警告,主要因为那些C库的函数,很多函数内部是不进行参数检测的(包括越界类的),微软担心使用这些会造成内存异常,所以就改写了同样功能的函数,改写了的函数进行了参数的检测,使用这些新的函数会更安全和便捷。关于这些改写的函数你不用专门去记忆,因为编译器对于每个函数在给出警告时,都会告诉你相应的安全函数,查看警告信息就可以获知,在使用时也再查看一下MSDN详细了解。库函数改写例子:
mkdir改写为 _mkdir 
fopen”改写为 fopen_s 
stricmp改写为 stricmp_s
sprintf改写为sprintf_s

strcpy改写为strcpy_s

    解决方案:
1> 根据下面的warning提示:参见“fopen”的声明
        消息:“This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.”
        所以可以将函数按warning提示的第二句,改为使用fopen_s函数即可:
        例如:FILE *pFile=fopen("1.txt", "w");
           改为:
           FILE* pFile;
           fopen_s(&pFile, "1.txt", "w"); 
2> 还是根据warning提示的地三句话:use _CRT_SECURE_NO_DEPRECATE
        项目|属性|配置属性|C/C++|命令行|附加选项,加入【/D "_CRT_SECURE_NO_DEPRECATE" 】(注:加入中括号中完整的内容)
3> 降低警告级别:项目|属性|配置属性|C/C++|常规,自己根据情况降低警告级别(此法不推荐)
    注意:高度重视警告:使用编译器的最高警告级别。应该要求构建是干净利落的(没有警告)。理解所有警告。通过 修改代码而不是降低警告级别来排除警告。

方法一:手工将原来的旧函数替换成新的Security CRT functions。 
方法二:屏蔽这个警告。 
            在预编译头文件stdafx.h里(注意:一定要在没有include任何头文件之前)定义下面的宏: 
            #define _CRT_SECURE_NO_DEPRECATE 
            或者#param warning(disable:4996) 
方法二没有使用新的更安全的CRT函数,显然不是一个值得推荐的方法,可是你又不想一个一个地改。 
那么还有一个更方便的方法: 
在预编译头文件stdafx.h里(同样要在没有include任何头文件之前)定义下面的宏: 
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 
在链接的时候便会自动将旧函数替换成Security CRT functions。 
注意:这个方法虽然使用了新的函数,但是不能消除警告你还得同时使用方法二。。。

2、SerialPort收数据时出现的BUGcomstat is being used without defining

比如:Run-Time Check Failure #3 - The variable 'comstat' is being used without being initialized.

CSerialPort类在Visual C++ .NET 应用时会出现意想不到的问题。以《Visual C++/Turobo C串口通信编程实践》(龚建伟 熊光明 著)一书中第二章的SerialPortTest程序为例,当在Visual C++ .NET下编写后之后,debug之后,会出现编译错误:“operator+="不明确,MSDN解释“为重载运算符定 
义了多个可能的运算符。可能的解决方案:对一个或多个实际参数使用显式转换。”当将

LONG CSerialPortTestDlg::OnComm(WPARAM ch, LPARAM port) 

m_strEditReceiveMsg +=ch; 
UpdateData(FALSE); //将接收到的字符显示在接收编辑框中 
return 0; 
}

中m_strEditReceiveMsg +=ch;改写为m_strEditReceiveMsg +=char(ch);后,debug顺利通过了。其实这个还不是CSerialPort类的问题。m_strEditReceiveMsg+=ch;改写为m_strEditReceiveMsg +=char(ch) 是应该的,这样更为严谨,因为在 OnComm(WPARAM ch, LPARAM port)函数中,ch 为 WPARAM 型数据,WPARAM型数据适应型很强,char(ch)将ch强制转换为char型,更适合CString型,这应该算是VC.NET的进步。

    当将这个问题解决之后,编译成功了。然后开始测试。向串口调试助手发送消息时一切正常。但从串口调试助手向SerialPortTest发送消息时,报错了,说“comstat is being used without defining",在SerialPort.CPP中,可以找到comstat的定义:COMSTAT comstat; 但将光标指向comstat时右键转到定义处或声明处,却均提示“未定义符号”,这便是CSerialPort类在VC.NET应用中的问题了。那该如何解决这个问题呢?在这,我们向大家提供两种解决方案:

方案1: 改变项目配置属性

    一种解决方案是改变基本运行时检查(changing the runtime checks in project settings):在菜单Project->Project properties-> C/C++ -> Code generation-> Basic Runtime checks --> change to 'Default',在中文版中是:项目-〉属性-〉配置属性-〉C/C++代码生成-〉基本运行时检查-〉设置为默认,当将基本运行时检查改为默认之后,编译自然顺利通过了,向串口调试助手发送消息正常了,再从串口调试助手向SerialPortTest发送消息时,也正常了。

方案2:改变comstat变量属性

     另一种解决方案是将CSerialPort.CPP中的COMSTAT comstat;改为static COMSTAT comstat;这样改了之后,debug顺利通过,然后调试,与串口调试助手相互发消息都OK了。为什么这样就能解决呢?其实当你使用debug解决方案时,它的基本运行时检查初始设置为:两者(/RTC1,等同于 /RTCsu),这个两者是指:堆栈帧(/RTCs),未初始化的变量(/RTCu)。由于它要检查未初始化的变量,所以将SerialPort.cpp中的COMSTAT comstat;改为static COMSTAT comstat;就可以正常使用CSerialPort类了。 
     以上是在debug下的解决方案,当在Release编译状态时,你会发现并不需要将COMSTAT comstat;改为static COMSTAT comstat;就能编译成功并且发送接收消息正常。其实,在Release下,它的基本运行时检查初始设置已为默认。这应该也算是第一种解决方案之内。 
    而当你将它设置为两者(/RTC1,等同于 /RTCsu)时,不论是否将COMSTAT comstat;改为static COMSTAT comstat;,编译都不能通过,报错““cl.exe”返回的结果有误。",这个应该是属于Release的问题了,另当别论了。

3、C++连接MYSQL

1)、新建一个工程,随便写一个helloworld,目的是就是让工程下的“debug”文件夹出现 
2)、把D:\Program Files\MySQL\MySQL Server 5.5\lib下面的libmysql.dll复制到工程的debug文件夹里面 
3)、接下来要设置一些引用文件的环境变量,首先,点击项目->属性->vc++目录。 
然后“include目录”那把“D:\Program Files\MySQL\MySQL Server 5.5\include”给加进来 
再然后“lib目录”那里把“D:\Program Files\MySQL\MySQL Server 5.5\lib”也一起加进来

VC6.0设置:

(1)打开VC6.0 工具栏Tools菜单下的Options选项,在Directories的标签页中右边的“Show directories for:”下拉列表中选中“Includefiles”,然后在中间列表框中添加你本地安装MySQL的include目录路径。(我的是D:\Program Files\MySQL\MySQL Server 5.5\include)。

(2)在上面说到的“Show directories for:”下拉列表中选中“Library files”,然后添加你本地安装MySQL的Lib目录路径。Lib目录下有debug目录,选debug。(我的是D:\Program Files\MySQL\MySQL Server 5.5\lib\debug)。

4)、然后在项目->属性窗口下点击:连接器->输入->附加依赖项,把"libmysql.lib"写进去

VC6.0设置:在“Project settings->Link:Object/library modules”里面添加“libmysql.lib”。

使用VC++编译时再添加以下项:

5)、在stdafx.h里面添加如下的内容: 
#include "mysql.h"

#include "winsock.h" // 如果编译出错,则把该行放到#include "mysql.h"之前#pragma comment(lib,"libmySQL.lib") // 如果在附加依赖项里已增加,则就不要添加了

3.1

1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_close@4,该符号在函数 _main 中被引用
1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_fetch_row@4,该符号在函数 _main 中被引用
1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_store_result@4,该符号在函数 _main 中被引用
1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_query@8 ,该符号在函数 _main 中被引用
1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_real_connect@32,该符号在函数 _main 中被引用
1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_options@12 ,该符号在函数 _main 中被引用
1>test.obj : error LNK2019: 无法解析的外部符号 _mysql_init@4,该符号在函数 _main 中被引用
1>D:\Program_Files\C&C++\test_mysql\Debug\test_mysql.exe : fatal error LNK1120: 7 个无法解析的外部命令

此异常是没有在项目属性的连接器中的“附加依赖项”中添加libmysql.dll。

 

3.2 编译正常,运行的时候报错:无法启动此程序,因为计算机中丢失libmysql.dll。尝试重新安装该程序解决此问题。

此问题是因为没有将解压后的mysql目录下lib/debug(opt)中的libmysql.dll拷贝到工程目录下(或debug目录中)。

 

3.3

1>c:\program files\mysql\mysql server 5.5\include\mysql_com.h(291): error C2146: 语法错误: 缺少“;”(在标识符“fd”的前面)
1>c:\program files\mysql\mysql server 5.5\include\mysql_com.h(291): error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\program files\mysql\mysql server 5.5\include\mysql_com.h(291): error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\program files\mysql\mysql server 5.5\include\mysql_com.h(470): error C2065: “SOCKET”: 未声明的标识符
1>c:\program files\mysql\mysql server 5.5\include\mysql_com.h(470): error C2146: 语法错误: 缺少“)”(在标识符“s”的前面)
1>c:\program files\mysql\mysql server 5.5\include\mysql_com.h(471): error C2059: 语法错误:“)”

上述错误原因要结合编译环境来解决。

1)windows.h头文件必须放在mysql.h之前;

2)在VS2008中,若已经执行了第一步却仍然不行,检查mysql.h之前是否有如下代码:

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料

上述语句通常在stdafx.h中。删掉该句即可。

 

3.4

>正在链接...
1>stdafx.obj : error LNK2005: "public: struct st_mysql_res * __thiscall DBUtil::ResultSet(char *)" (?ResultSet@DBUtil@@QAEPAUst_mysql_res@@PAD @Z ) 已经在 PreThread.obj 中定义
1>stdafx.obj : error LNK2005: "public: __thiscall DBUtil::~DBUtil(void)" (??1DBUtil@@QAE@XZ ) 已经在 PreThread.obj 中定义
1>stdafx.obj : error LNK2005: "public: void __thiscall DBUtil::Init(void)" (?Init@DBUtil@@QAEXXZ) 已经在 PreThread.obj 中定义
1>stdafx.obj : error LNK2005: "public: __thiscall DBUtil::DBUtil(char *,char *,char *,char *)" (??0DBUtil@@QAE@PAD000@Z ) 已经在 PreThread.obj 中定义
1>stdafx.obj : error LNK2005: "public: __thiscall DBUtil::DBUtil(void)" (??0DBUtil@@QAE@XZ ) 已经在 PreThread.obj 中定义
1>D:\Program_Files\Multi-Core\XOJ_ACS\Release\XOJ_ACS.exe : fatal error LNK1169: 找到一个或多个多重定义的符号

头文件被重复包含

4.“MessageBoxW”: 不能将参数 2 从“const char [1]”转换为“LPCWSTR”

(部分摘自:http://topic.csdn.net/u/20080412/19/89EFF60A-C2C0-492F-BC04-FC68B3B5B6FB.html

因为你的程序在UNICODE(宽字节)字符集下运行,如果调用了 MessageBox ,实际上调用的是 MessageBoxW 函数; 
如果你的程序在 ANSI 字符集运行,调用 MessageBox ,就相当于调用 MessageBoxA; 
其中 MessageBoxW 支持 UNICODE; 
MessageBoxA 支持ANSI; 
UNICODE与ANSI 有什么区别呢?简单的说,UNICODE版的字符比ANSI 的内存占用大,比如: 
Win32程式中出现的标准定义 char 占一个字节, 
而 char 的UNICODE版被定义成这样: 
typedef unsigned short wchar_t ;占2个字节。 
所以有字符做参数的函数相应也用两个版本了。 
宽字节版函数中带有字符参数的都应该用宽字节版的字符参数,将字符串转换成宽字节很容易: 
比如将 "Application Error" 转换成UNICODE版,只需在它前面使用一个定义了的宏,如下: 
L"Application Error" ,或者TEXT("Application Error" )都可以 
所以你应将 MessageBox(NULL,Temp,"Application Error",MB_ICONSTOP); 改为: 
          MessageBox(NULL,Temp,L"Application Error",MB_ICONSTOP);

5、fatal error LNK1107: 文件无效或损坏: 无法在 0x278 处读取

该问题可能是引入的库不正确,但是经过查看,引入的文件以及库均正确,仅仅是删除了项目属性,连接器中的“附加依赖项”中的值,本项试试删除该项是否会导致程序无法运行,结果显示这个错误。等再次加上的时候,依然无效,索性将所有引入的文件以及库均删除,全部重新添加,问题解决。

6、 编译正常,运行的时候报错:"0x0041596d" 指令引用的"0x00000000"内存。该内存不能为"written"。
错误原因:这是指针结构没初始化,而引用产生的地址错误
如下:
char *hostname = "localhost";
char *username = "root";
char *pass = "111";//你的mysql服务器密码
char *dbname = "mysql";
unsigned int port = 3306; //server port  
struct Database_Param *mysql_param;//没有初始化就引用了
struct Data_Param *db_param;  //没有初始化就引用了

int main()
{

 CDatabase MySqldb;

 mysql_param->host = hostname;
 mysql_param->user = username;
 mysql_param->password =pass;
 mysql_param->db = dbname;
 mysql_param->port = 3306;
 //mysql_param->unix_socket,NULL;
 mysql_param->client_flag = 0;
 //mysql_param = &db_param;
 db_param->db_name = mysql_param->db;


修改后:
char *hostname = "localhost";
char *username = "root";
char *pass = "111";//你的mysql服务器密码
char *dbname = "mysql";
unsigned int port = 3306; //server port  
struct Database_Param *mysql_param;
struct Data_Param *db_param;

int main()
{

 CDatabase MySqldb;

 mysql_param = new (struct Database_Param );//对指针先初始化后引用
 db_param = new (struct Data_Param);

 mysql_param->host = hostname;
 mysql_param->user = username;
 mysql_param->password =pass;
 mysql_param->db = dbname;
 mysql_param->port = 3306;
 //mysql_param->unix_socket,NULL;
 mysql_param->client_flag = 0;
 //mysql_param = &db_param;
 db_param->db_name = mysql_param->db;

7、error C2593: “operator +=”不明确 

处理串口输入事件时

afx_msg LRESULT CSerialPortptestDlg::OnComm(WPARAM wParam, LPARAM lParam)
{
 m_strEditReceiveMsg += wParam;
 UpdateData(FALSE);  //将接收到的字符显示在接收编辑框中
 return 0;
 return 0;
}

编译时出现“operator   +=”不明确,也就是m_strEditReceiveMsg += wParam;
改正方法:

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

1>i:\prj\commterm\commterm\serial\serialport.cpp(23): error C2664: “CreateFileW”: 不能将参数 1 从“const char *”转换为“LPCWSTR”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换

点击项目->属性->配置属性->常规 
然后“字符集”那把“使用 Unicode 字符集”改为“未设置”或“使用多字节字符集” 
再然后“lib目录”那里把“D:\Program Files\MySQL\MySQL Server 5.5\lib”也一起加进来

 

#include "stdafx.h"
#include <winsvc.h>
如果颠倒了,就会出现下面一堆令人头疼的错误:

正在编译...
ServerTest.cpp
e:\Project C++\ServerTest\ServerTest\ServerTest\ServerTest.cpp(58) : error C2146: 语法错误 : 缺少“;”(在标识符“hServStatus”的前面)
e:\Project C++\ServerTest\ServerTest\ServerTest\ServerTest.cpp(58) : error C2501: “hServStatus” : 缺少存储类或类型说明符
e:\Project C++\ServerTest\ServerTest\ServerTest\ServerTest.cpp(59) : error C2146: 语法错误 : 缺少“;”(在标识符“hSStat”的前面)
e:\Project C++\ServerTest\ServerTest\ServerTest\ServerTest.cpp(59) : error C2501: “hSStat” : 缺少存储类或类型说明符
e:\Project C++\ServerTest\ServerTest\ServerTest\ServerTest.cpp(75) : error C2065: “SERVICE_TABLE_ENTRY” : 未声明的标识符
e:\Project C++\ServerTest\ServerTest\ServerTest\ServerTest.cpp(75) : error C2146: 语法错误 : 缺少“;”(在标识符“DispatchTable”的前面)

 

在控制台下写程序
控制台下用windows API写比较好。用这个类型:CRITICAL_SECTION g_cs;
然后 InitializeCriticalSection(...)
   EnterCriticalSection(...);
   LeaveCriticalSection(...);

  CRITICAL_SECTION m_sec;
  InitializeCriticalSection( &m_sec );
  DeleteCriticalSection( &m_sec );
  EnterCriticalSection( &m_sec );
  LeaveCriticalSection( &m_sec );
 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!