当前位置: 首页 > 编程日记 > 正文

ATL::CStringA和std::string之间转换的一些误区

对于刚做windows下VC的开发同学,类型转换应该是一个令其很苦恼的问题。我刚写工作的时候,也为这类问题不停的在网上搜索转换方法。最近工作中遇到一个“神奇”的bug(一般“神奇”的问题往往是低级错误导致的),最后跟踪发现还是类型转换问题。(转载请指明出处)

ATL::CStringA和std::string都可以“接受”\0,也就是说,在CStringA的对象的内容和std::string类型数据中可以包含多个\0,而不是最后一位是\0,。这个可能是很多人对它们认识的一个误区。

贴一下测试的相关代码

// string.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <string>std::string RetCommonString()
{std::string str = "ABCDE\0FGH";return str;
}std::string RetBreakString()
{std::string str = "";char charrayp[9];charrayp[0] = 'A';charrayp[1] = 'B';charrayp[2] = 'C';charrayp[3] = 'D';charrayp[4] = 'E';charrayp[5] = '\0';charrayp[6] = 'F';charrayp[7] = 'G';charrayp[8] = 'H';str.append( charrayp, 9);return str;
}ATL::CStringA RetCommonCStringA()
{ATL::CStringA strA = "ABCDE\0FGH";return strA;
}ATL::CStringA RetBreakCStringA()
{ATL::CStringA strA = "";char charrayp[9];charrayp[0] = 'A';charrayp[1] = 'B';charrayp[2] = 'C';charrayp[3] = 'D';charrayp[4] = 'E';charrayp[5] = '\0';charrayp[6] = 'F';charrayp[7] = 'G';charrayp[8] = 'H';LPSTR lpTmp = strA.GetBuffer(9);if ( NULL !=  lpTmp ){memcpy( (void*)lpTmp, charrayp, 9 );}strA.ReleaseBuffer(9);return strA;
}int _tmain(int argc, _TCHAR* argv[])
{ATL::CStringA strCommonCStringA = RetCommonCStringA();ATL::CStringA strBreakCStringA = RetBreakCStringA();void* pstrCommonCStringA = &strCommonCStringA;void* pstrBreakCStringA = &strBreakCStringA;std::string strCommonString = RetCommonString();std::string strBreakString = RetBreakString();void* pstrCommonString = &strCommonString;void* pstrBreakString = &strBreakString;{int nstrBreakCStringA = strBreakCStringA.GetLength();int nstrCommonCStringA = strCommonCStringA.GetLength();if ( nstrBreakCStringA == nstrCommonCStringA ){// 这儿不会相等ATLASSERT(FALSE);}std::string::size_type lstrBreakStringLength = strBreakString.length();std::string::size_type lstrCommonStringLength = strCommonString.length();if ( lstrCommonStringLength ==  lstrBreakStringLength ){// 这儿不会相等ATLASSERT(FALSE);}}// std::string转CStringA的正确方法,但存在长度限制{std::string::size_type lstringlength = strBreakString.length();ATL::CStringA CStringAobj = "";LPSTR lpCStringAobj = CStringAobj.GetBuffer( (int)lstringlength );memcpy( (void*) lpCStringAobj, strBreakString.c_str(), lstringlength );CStringAobj.ReleaseBuffer((int)lstringlength);std::string::size_type lstrBreakStringLength = strBreakString.length();int nCStringobj = CStringAobj.GetLength();if ( lstrBreakStringLength != nCStringobj ){ATLASSERT(FALSE);}// 内容就不比较了,直接在调试时看内存}// std::string转CStringA的错误方法{// ERROR: CStringAObj = stringobj.c_str(){ATL::CStringA CStringAobj = strBreakString.c_str();std::string::size_type lstrBreakStringLength = strBreakString.length();int nCStringobj = CStringAobj.GetLength();if ( lstrBreakStringLength != nCStringobj ){ATLASSERT(FALSE);}}// ERROR: CStringobj = CStringA( stringobj.c_str() );{ATL::CStringA CStringAobj( strBreakString.c_str() ) ;std::string::size_type lstrBreakStringLength = strBreakString.length();int nCStringobj = CStringAobj.GetLength();if ( lstrBreakStringLength != nCStringobj ){ATLASSERT(FALSE);}}// ERROR: CStringAobj.Format( "%s", stringobj.c_str() );{ATL::CStringA CStringAobj;CStringAobj.Format( "%s", strBreakString.c_str() );std::string::size_type lstrBreakStringLength = strBreakString.length();int nCStringobj = CStringAobj.GetLength();if ( lstrBreakStringLength != nCStringobj ){ATLASSERT(FALSE);}}}// CStringA转std::string的正确方法{int nstrBreakCStringALength = strBreakCStringA.GetLength();LPSTR lpstrBreakCStringA = strBreakCStringA.GetBuffer( nstrBreakCStringALength );strBreakCStringA.ReleaseBuffer( nstrBreakCStringALength );std::string strobj = "";strobj.append( lpstrBreakCStringA, nstrBreakCStringALength );std::string::size_type lstrobjLength = strobj.length();int nCStringobj = strBreakCStringA.GetLength();if ( lstrobjLength != nCStringobj ){ATLASSERT(FALSE);}}// ERROR: stringobj = CStringAObj{std::string strobj = strBreakCStringA;std::string::size_type lstrobjLength = strobj.length();int nCStringobj = strBreakCStringA.GetLength();if ( lstrobjLength != nCStringobj ){ATLASSERT(FALSE);}}return 0;
}

调试这个程序,我们查看一下相关内存。

std::string类型数据strBreakString(内容为"ABCDE\0FGH") 的在内存中的数据如下图

红线标志的09就是这个strBreakString的长度。

std::string类型数据strCommonString(内容为"ABCDE") 的在内存中的数据如下图

红线标志的05就是这个strCommonString的长度。

查看一下strBreakString和strCommonString的来源,可以看出,给std::string类型数据用=赋值,如果内容中包含\0,则std::string类型数据只能接受\0之前的数据。所以strCommonString的数据只有\0之前的ABCDE。而使用std::string的append方法,将会将\0也赋值进去。

我们再看一下ATL::CStringA对象在内存中的数据形式。

ATL::CStringA类型数据strBreakCStringA (内容为"ABCDE\0FGH") 的在内存中的数据如下图

红线标志的09就是这个strBreakCStringA 的长度。

ATL::CStringA类型数据strCommonCStringA (内容为"ABCDE") 的在内存中的数据如下图

红线标志的05就是这个strCommonCStringA 的长度。

查看一下strBreakCStringA 和strCommonCStringA 的来源,可以看出,给ATL::CStringA类型数据用=赋值,如果内容中包含\0,则ATL::CStringA类型数据只能接受\0之前的数据。所以strCommonCStringA 的数据只有\0之前的ABCDE。而使用ATL::CStringA的GetBuffer、ReleaseBuffer等方法,再加上memcpy,可以将\0也赋值进去。

如果方便,可以调试一下这个例子。可以发现网上一些std::string和ATL::CStringA之间的转换方法存在错误。如:网上有些方法是CStringAObj = stringobj.c_str(),或者CStringAobj.Format( "%s", stringobj.c_str() ),这些方法都会导致ATL::CStringA对象的内容可能被std::string中的存在的\0截断。而正确的方法大致如下框架

{std::string::size_type lstringlength = strBreakString.length();ATL::CStringA CStringAobj = "";LPSTR lpCStringAobj = CStringAobj.GetBuffer( (int)lstringlength );memcpy( (void*) lpCStringAobj, strBreakString.c_str(), lstringlength );CStringAobj.ReleaseBuffer((int)lstringlength);std::string::size_type lstrBreakStringLength = strBreakString.length();int nCStringobj = CStringAobj.GetLength();if ( lstrBreakStringLength != nCStringobj ){ATLASSERT(FALSE);}// 内容就不比较了,直接在调试时看内存}

(转载请指明出处)

相关文章:

Windows XP鲜为人知的70招

一、Windows XP优化恢复Windows经典界面很多人安装了Windows XP后的第一感觉就是Windows变得漂亮极了。只是可惜美丽的代价要耗掉我们本就不富裕的内存和显存。要想恢复到和经典Windows类似的界面和使用习惯&#xff0c;请在桌面上单击鼠标右键&#xff0c;选择“属性”命令即可…

Github开源趋势榜Top 1:英伟达升级发布二代StyleGAN,效果更完美

整理 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;2018 年底&#xff0c;英伟达借鉴风格迁移的思路&#xff0c;提出当时最先进的无条件生成模型—— StyleGAN &#xff0c;吸引了大家广泛关注。随后&#xff0c;代码开源&#xff0c;一位 Uber …

百度地图 ip查询 service

官方文档&#xff1a;http://developer.baidu.com/map/wiki/index.php?titlewebapi/ip-api 请求 一个例子&#xff1a; http://api.map.baidu.com/location/ip?ak3GFi2F04wXaVuwmGu8fN49kL1234567890&ip180.161.128.181 返回 {"address": "CN|\u6cb3\u535…

python3编写简易统计服务器

打点这个功能总是美其名曰“帮助提升用户体验”&#xff0c;其实说白了就是记录用户做了哪些操作。目前国内很多通用软件都做了相关功能&#xff0c;像360、QQ等这样的以用户体验出众的软件&#xff0c;其打点的面自然也很广很细。当然这种“侵犯”用户隐私的事情在业内各个公司…

作价20亿美元!英特尔收购以色列AI芯片公司Habana Labs

出品 | AI科技大本营&#xff08;ID:rgznai1000&#xff09;12月16日&#xff0c;英特尔宣布以约 20 亿美元收购以色列公司Habana Labs&#xff0c;这成为英特尔在以色列仅次于 Mobileye&#xff08;153 亿美元&#xff09; 的第二大收购案。Habana Labs 成立于 2016 年&#x…

这就是奇客文化?简直太有才了!

这就是奇客文化&#xff1f;简直太有才了……

java中的char类型

2019独角兽企业重金招聘Python工程师标准>>> 一&#xff1a;char的初始化 char是Java中的保留字&#xff0c;与别的语言不同的是&#xff0c;char在Java中是16位的&#xff0c;因为Java用的是Unicode。不过8位的ASCII码包含在Unicode中&#xff0c;是从0~127的。 Ja…

[原创] 如何追踪每一笔记录的来龙去脉:一个完整的Audit Logging解决方案—Part I...

一、提出问题 在开发一个企业级 应用的时候&#xff0c;尤其在一个涉及到敏感数据的应用&#xff0c;比如财务系统、物流系统&#xff0c;我们往往有这样的需求&#xff1a;对于数据库中每一笔数据的添加、修改和删除&#xff0c;都需要有一个明确的日志&#xff0c;以便我们可…

进程间通信:同步双工管道

因为工作需要&#xff0c;需要设计出一个双工的IPC。&#xff08;转载请指明出处&#xff09;在一番比较后&#xff0c;我发现管道是比较符合我们的需求的。但是我们需求要求管道的对方是可信任的&#xff0c;而在vista以下系统是没有GetNamedPipeClientProcessId、GetNamedPip…

就因为一个笔记本,运营和产品吵得不可开交......

上班最讨厌的一件事情&#xff0c;莫过于开会&#xff0c;因为每次开会感觉就要吵架&#xff0c;这个今天开会又吵架了&#xff0c;吵架竟然是因为产品小姐姐的笔记本。产品小姐姐用了一本可擦笔记本记录会议内容&#xff0c;运营小姐姐竟然说这个本子有什么用&#xff0c;不就…

Ka的递归编程练习 Part4|Hanoi汉诺塔,双色汉诺塔的也有

1 #include <stdio.h>2 void hanoi(int s,char a,char b,char c) //a是出发盘&#xff0c;b是中途盘&#xff0c;c是结束盘 3 {4 if(s0) return;5 hanoi(s-1,a,c,b); //把最底下的从a借助c移动到b6 printf("%d from %c move to %c\n",s,a,c);7 …

一种精确从文本中提取URL的思路及实现

在今年三四月份&#xff0c;我接受了一个需求&#xff1a;从文本中提取URL。这样的需求&#xff0c;可能算是非常小众的需求了。大概只有QQ、飞信、阿里旺旺等之类的即时通讯软件存在这样的需求。在研究这个之前&#xff0c;我测试了这些软件这块功能&#xff0c;发现它们这块的…

解读 | 2019年10篇计算机视觉精选论文(上)

作者 | 神经小兮来源 | HyperAI超神经&#xff08;ID:HyperAI&#xff09;2019 年转眼已经接近尾声&#xff0c;我们看到&#xff0c;这一年计算机视觉&#xff08;CV&#xff09;领域又诞生了大量出色的论文&#xff0c;提出了许多新颖的架构和方法&#xff0c;进一步提高了视…

不错的工具:Reflector for .NET

下载地址: http://www.aisto.com/roeder/dotnet/ 注意&#xff1a;下载时要输一些注册信息&#xff0c;输入用户名时&#xff0c;中间要加一个空格。

Possible MySQL server UUID duplication for server

&#xfeff;&#xfeff;在mysql enterprise monitor监控过程中出现这样的event事件&#xff0c;Topic: Possible MySQL server UUID duplication for server 事件&#xff0c;从该提示的描述来看貌似是存在重复的uuid&#xff0c;而实际上主从关系并不存在重复的uuid。主从关…

使用VC实现一个“智能”自增减线程池

工作中接手了一款产品的改造。因为该产品可能使用很多线程&#xff0c;所以产品中使用了线程池。&#xff08;转载请指明来自BreakSoftware的CSDN博客&#xff09; 线程池的一个优点是降低线程创建和销毁的频率&#xff1b;缺点是可能在比较闲的时候还存在一定数量的空闲线程。…

国内外财务软件科目结构的比较

科目结构是整个会计核算的基础。国内外财务软件都是任意定义科目的分段及科目编码长度&#xff0c;一般都能支持六段到九段。但科目结构在不同的国家有不同的规范&#xff0c;因而在不同的财务软件中也就有不同的控制。在科目分类上&#xff0c;国内外有明显的区别。国外财务软…

朋友圈装死,微博蹦迪,Python教你如何掌握女神情绪变化 | CSDN博文精选

作者 | A字头来源 | 数据札记倌很多人都是在朋友圈装死&#xff0c;微博上蹦迪。微信朋友圈已经不是一个可以随意发表心情的地方了&#xff0c;微博才是&#xff01;所以你不要傻傻盯着女神的朋友圈发呆啦&#xff01;本文教你如何用Python自动通知女神微博情绪变化&#xff0c…

java异常笔记

Throwable是所有Java程序中错误处理的父类&#xff0c;有两种资类&#xff1a;Error和Exception。Error&#xff1a;表示由JVM所侦测到的无法预期的错误&#xff0c;由于这是属于JVM层次的严重错误&#xff0c;导致JVM无法继续执行&#xff0c;因此&#xff0c;这是不可捕捉到的…

2019最新进展 | Transformer在深度推荐系统中的应用

作者 | Alex-zhai来源 | 深度传送门&#xff08;ID:deep_deliver&#xff09;【导读】最近基于Transformer的一些NLP模型很火&#xff08;比如BERT&#xff0c;GPT-2等&#xff09;&#xff0c;因此将Transformer模型引入到推荐算法中是近期的一个潮流。Transformer比起传统的L…

自己架设windows升级服务器

大部分对计算机比较熟悉的朋友都知道&#xff0c;通常安装好Windows 操作系统后要做的第一件事就是上Windows Update网站去给Windows 安装补丁程序&#xff0c;否则各种漏洞对系统就是一个很大的威胁。不过遗憾的是很多人还没有这样的意识&#xff0c;疏忽了给系统打补丁。这也…

内嵌IE网页窗口中消除IE默认脚本设置影响的方法

随着人们对客户端软件界面要求的不断提高,软件开发商面临着一个问题:如何快速廉价开发出各种丰富效果的UI界面。设计出一套丰富控件的界面库是不容易的,且产品经理丰富的想法和UED对效果的追求,往往会使程序员疲于编写这些“效果控件”。目前市面上使用的很多界面库是基于X…

win7 64位操作系统中 Oracle 11g 安装教程(图解)

1.下载Oracle 11g R2 for Windows版本&#xff0c;下载地址如下  官方网站&#xff1a;  http://download.oracle.com/otn/nt/oracle11g/112010/win32_11gR2_database_1of2.zip http://download.oracle.com/otn/nt/oracle11g/112010/win32_11gR2_database_2of2.zip 2.解压两…

使用APIHOOK实现进程隐藏

今天翻出一些今年前写的代码。其中一个是09年&#xff0c;我帮一个读研的同学写的一个“无公害恶意”程序。大致要求就是要实现自启动和自我隐藏。我使用的都是些简单的技术&#xff0c;只是实现自我隐藏稍微让我花费了点时间写算法。其实这个算法也很简单&#xff0c;就是大学…

程序员创业前要做哪些准备?

作者 | hsm_computer出品 | CSDN博客在互联网时代&#xff0c;不少干IT的人白手起家&#xff0c;在短短的几年里通过努力干出了一番事业&#xff0c;有房有车有公司&#xff0c;在人前也很光鲜。这就吸引了更多的程序员想要通过自主创业来实现财务自由。殊不知&#xff0c;创业…

Flex编码过程

Flex编码过程当我们开发一个Flex程序&#xff0c;我们重复其他类型网络程序的过程&#xff0c;例如HTML,JSP,ASP和CFML。创建一个有用的Flex程序是很容易的&#xff1a;打开我们最喜欢的文本编辑器&#xff0c;例如Flex Builder&#xff0c;输入XML标签&#xff0c;编译成为SWF…

BufferedWriter

package JBJADV003;import java.io.*;public class BufferedWriterTest { public static void main(String[] args) { try { //创建一个FileWriter 对象 FileWriter fwnew FileWriter("c:\\myDoc\\hello.txt"); //创建一个BufferedWriter 对象 BufferedWriter bwnew…

使用VC内嵌Python实现的一个代码检测工具

最近组内准备整顿代码&#xff0c;领导让我写个简单的python脚本分析代码中注释的行数和无效注释。因为这个需求不是很急&#xff0c;所以我想把简单的事情做复杂点。于是就写了一个用VC内嵌Python&#xff0c;并通过模拟按键和发消息去控制其他软件的工具。&#xff08;转载请…

Python如何实现24个微信大群万人同步转发直播?

作者 | 猪哥66来源 | CSDN博客今天我们来学习微信机器人多群转发做同步图文直播&#xff01;一、背景介绍猪哥一年前在建Python学习群的时候就说过&#xff0c;要邀请企业大佬来学习群做直播。其实文章早就写好了&#xff0c;但是一直没有找到好的转发软件&#xff0c;所以耽搁…

ITSM实施三招[案例]

当前国外成熟的ITSM解决方案的实施成本相对比较高&#xff0c;使一些对成本较敏感的的IT部门&#xff0c;成为ITSM实施的一个真空区。对于国内起步阶段的ITSM&#xff08;IT服务管理&#xff09;实施来说&#xff0c;南航的ITSM实施之路是一个借鉴。 南航it环境 在各大航空公司…