下面的代码没有给出任何错误/错误/警告(虽然我认为可能会发生一些非法的内存访问)。奇怪的是,使用2种不同方法打印的字符串的大小(strlen和std :: string.size()的出现方式不同。
strlen(l_str.c_str() - >给出1500的大小,而, l_str.size() - >将大小设为0。
#include <string.h>
#include <string>
#include <stdio.h>
#include<iostream>
using namespace std;
void strRet(void* data)
{
char ar[1500];
memset(ar,0,1500);
for(int i=0;i<1500;i++)
ar[i]='a';
memset(data,0,1500); // This might not be correct but it works fine
memcpy(data,ar,1500);
}
int main()
{
std::string l_str;
cout<<endl<<"size before: "<<l_str.length();
int var=10;
strRet((void *)l_str.c_str());
printf("Str after call: %s\n",l_str.c_str());
cout<<endl<<"size after(using strlen): "<<strlen(l_str.c_str());
cout<<endl<<"Size after(using size function): "<<l_str.size();
printf("var value after call: %d\n",var);
return 0;
}
如果我做了一些我不应该做的事情,请提出建议!
另外,当我memset(data,0,1500);
时,我想知道哪些内存字节被设置为0?我的意思是,如果假设我的字符串变量的起始地址是100,那么memset命令是否将内存范围[100,1600]设置为0?或者是否设置了其他一些内存范围?
答案 0 :(得分:4)
memset(data,0,1500); // This might not be correct but it works fine
这是不正确的,它并没有“正常工作”。这是未定义的行为,你犯了一个常见的错误,即如果它编译,你的计算机没有立即着火,一切都很好。
实际上并非如此。
我做过一些我不应该做的事情!
是的,你有。你拿了一个指向std::string
的指针,这是一个非平凡的对象,它有自己的状态和行为,要求它输入一些内存它控制的地址,并将其转换为{{1} }。
没有理由这样做,你应该非常很少在C ++代码中看到void*
,并且看到任何类型的C风格转换都非常令人担忧。
不要将void*
指针放入具有void*
等状态和行为的对象,直到您了解自己在做什么以及为什么这是错误的。然后,当那一天到来时,你仍然不会这样做,因为你会更清楚。
我们可以在一些细节上看第一个问题,如果它有帮助:
std::string
(void *)l_str.c_str()
返回什么?指向c_str()
l_str
的业务。如果此标准库实现使用小字符串优化,则它可能 in l_str
对象。如果没有,可以动态分配。l_str
的业务。我们可以肯定地说,至少有一个合法可寻址的char(l_str
)并且使用地址l_str.c_str()[0] == '\0'
是合法的(但仅作为一个过去的指针) ,所以你不能取消引用它)所以,声明
l_str.c_str()+1
将strRet((void *)l_str.c_str());
指针传递给包含一个或多个可寻址字符的位置,其中第一个为零。那是我们可以说的一切。
现在让我们再看一下有问题的一行
strRet
为什么我们期望在这个位置有1500个字符?如果您将memset(data,0,1500); // This might not be correct but it works fine
记录为需要至少1500个已分配字符的缓冲区,那么当您知道 strRet
时,实际传递l_str.c_str()
是否合理默认构造为空字符串?这不像您要求l_str
为您分配该存储空间。
你可以通过调用
让l_str
有机会分配你想要写的内存来开始这项工作。
l_str
在致电l_str.reserve(1500);
之前。这仍然不会通知strRet
您用l_str
填充它,因为您通过更改其背后的原始内存来做到这一点。
如果您希望此功能正常运行,则可以用
替换整个'a'
strRet
或者,如果要使用
正确更改现有字符串std::string l_str(1500, 'a');