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

一、将过去的工程用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 
那么如何搞定这些警告呢: html

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

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。 
注意:这个方法虽然使用了新的函数,可是不能消除警告你还得同时使用方法二。。。 c++

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

好比: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解释“为重载运算符定 
义了多个可能的运算符。可能的解决方案:对一个或多个实际参数使用显式转换。”当将 windows

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应用中的问题了。那该如何解决这个问题呢?在这,咱们向你们提供两种解决方案: socket

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

    一种解决方案是改变基本运行时检查(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的问题了,另当别论了。

三、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);

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

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

六、 编译正常,运行的时候报错:"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;

七、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 );  

相关文章
相关标签/搜索