string 内部使用的是智能指针?

蠓虫带着秤砣飞 2019-12-27 08:04:07
今天听到一个说法,说是string内部使用的是智能指针。
起因是这样的:
DLL间调用,传参,参数里面有了string类型。有人说这样很危险,是不安全的,会引起崩溃(不同模块间释放内存因为的崩溃)。
我说不会啊,传递的参数不会在另外的DLL里面释放。
那边说,string里面用的是智能指针,是引用计数的。会造成释放的时机不可控。
看string类的源码也没有看到智能指针的使用。但我不知道怎么确认这个问题。
有没有确认问题的思路呢?请指点。
...全文
199 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 15 楼 gouyanfen 的回复:
本质上他是个类,参数传递的主要是数据,不管他内部实现如何,用他做参数必然会带来后续很多问题的。不用最好
明白了,多谢。
寻开心 2019-12-28
  • 打赏
  • 举报
回复
关于智能指针,应该是两点:
1 对于编译器来说,智能指针实际上是一个栈对象,并非指针类型
在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。
2 不是为每个数据做一个copy,而是通过引用计数来重用数据。

string里面是否使用智能指针,听谁说都不如自己来做个实验来验证一下
void printString(const string& s ) {
unsigned char * pS = (unsigned char *) &s;
const char * pCS = s.c_str();
cout << hex << (long &) pS << " " << (long&) pCS << endl; // 输出string对象的地址, 以及内部字符传指针当地址
// 甚至还可以把pS对应的数据输出,看看内存结构如何
}

int main () {
string s1 = “0123”; // 构造,对象在栈的时候。 也可以再构造一个 const string s3; 来验证此时对象又在哪儿
printString(s1); // 看看数据放哪儿了, 很可能是栈对象
s1 = "012345"; // 修改, 验证字符串改变的时候,内部指针变量是如何处理的
printfString(s1); // 看看指针是否改变, 如果指针没有改变, 把s1赋予一个很长的字符串看看

string * s2 = new string("abcd"); // 动态申请
printString(s2); // 看看对象在堆的时候, 内部指针在哪儿
}

做实验吧, 估计不同的编译器的结果会有不同的差异。

验证上面之后,你还可以去验证把指针赋值给不同的对象后, 不同的对象的c_str()返回指针是否同一个, 借此可以判定是否是智能指针

这不应该是c++标准的问题, 是编译器实现的问题, 研究研究有利于了解c++对象的内存结构和实现原理,可以琢磨琢磨的
gouyanfen 2019-12-28
  • 打赏
  • 举报
回复
引用 14 楼 zjq9931 的回复:
[quote=引用 11 楼 lin5161678 的回复:] vs20XX 你写一个std::string 然后鼠标摆上去 然后按一下F12 你能看到string的完整实现
其实我也不比去纠结了,只要记住,参数别用string就好。[/quote] 本质上他是个类,参数传递的主要是数据,不管他内部实现如何,用他做参数必然会带来后续很多问题的。不用最好
  • 打赏
  • 举报
回复
引用 7 楼 lin5161678 的回复:
dll接口当然是套extern "C" 啦 写什么string 呀 就算没智能指针 2个模块使用的string实现不同 也只是换一个姿势死掉而已
明白了谢谢。 主要是跨模块释放造成的,或者是不同的string实现造成的。 那么能说说string里面是不是智能指针的问题呢? 这个我是真没有找到相关的说法。
  • 打赏
  • 举报
回复
引用 6 楼 寻开心 的回复:
太久了, 不记得了。 百度上搜了一下 https://www.cnblogs.com/abella/p/9582549.html
明白了不是什么智能指针的事情,就是跨模块释放的问题。 这个明白了。只要能保证不跨模块释放就可以了。 能说说智能指针的问题吗?
  • 打赏
  • 举报
回复
引用 11 楼 lin5161678 的回复:
vs20XX 你写一个std::string 然后鼠标摆上去 然后按一下F12 你能看到string的完整实现
其实我也不比去纠结了,只要记住,参数别用string就好。
  • 打赏
  • 举报
回复
引用 11 楼 lin5161678 的回复:
vs20XX 你写一个std::string 然后鼠标摆上去 然后按一下F12 你能看到string的完整实现
看过的,没有使用智能指针。 我拿这个去说,那位说了,没有并不能代表没有使用。。。。我也是郁闷了。。。
  • 打赏
  • 举报
回复
引用 10 楼 寻开心 的回复:
关于智能指针,应该是两点: 1 对于编译器来说,智能指针实际上是一个栈对象,并非指针类型 在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。 2 不是为每个数据做一个copy,而是通过引用计数来重用数据。 string里面是否使用智能指针,听谁说都不如自己来做个实验来验证一下 void printString(const string& s ) { unsigned char * pS = (unsigned char *) &s; const char * pCS = s.c_str(); cout << hex << (long &) pS << " " << (long&) pCS << endl; // 输出string对象的地址, 以及内部字符传指针当地址 // 甚至还可以把pS对应的数据输出,看看内存结构如何 } int main () { string s1 = “0123”; // 构造,对象在栈的时候。 也可以再构造一个 const string s3; 来验证此时对象又在哪儿 printString(s1); // 看看数据放哪儿了, 很可能是栈对象 s1 = "012345"; // 修改, 验证字符串改变的时候,内部指针变量是如何处理的 printfString(s1); // 看看指针是否改变, 如果指针没有改变, 把s1赋予一个很长的字符串看看 string * s2 = new string("abcd"); // 动态申请 printString(s2); // 看看对象在堆的时候, 内部指针在哪儿 } 做实验吧, 估计不同的编译器的结果会有不同的差异。 验证上面之后,你还可以去验证把指针赋值给不同的对象后, 不同的对象的c_str()返回指针是否同一个, 借此可以判定是否是智能指针 这不应该是c++标准的问题, 是编译器实现的问题, 研究研究有利于了解c++对象的内存结构和实现原理,可以琢磨琢磨的
试验是做过,并不能证明是不是智能指针。。
lin5161678 2019-12-28
  • 打赏
  • 举报
回复
vs20XX
你写一个std::string 然后鼠标摆上去
然后按一下F12
你能看到string的完整实现
lin5161678 2019-12-27
  • 打赏
  • 举报
回复
dll接口当然是套extern "C" 啦
写什么string 呀
就算没智能指针
2个模块使用的string实现不同 也只是换一个姿势死掉而已
寻开心 2019-12-27
  • 打赏
  • 举报
回复
太久了, 不记得了。 百度上搜了一下
https://www.cnblogs.com/abella/p/9582549.html
  • 打赏
  • 举报
回复
引用 3 楼 寻开心 的回复:
以前看到过微软做的解释,说是对dll改成多线程调用模式可以规避这个问题 太久了不写代码了,记不太清楚了
能否给一下微软相关的文档?
  • 打赏
  • 举报
回复
如果相互传递const引用呢? 地址变了没有什么,很有可能是重新分配了内存啊。 如果获取到的地址和静态存储的地址是一样的,确实会存在这个问题。 但如果是动态分配的内存就不会存在这个问题吧。 拷贝构造函数的实现也不难啊。 为了节约内存,搞出来的这种问题?
寻开心 2019-12-27
  • 打赏
  • 举报
回复
以前看到过微软做的解释,说是对dll改成多线程调用模式可以规避这个问题
太久了不写代码了,记不太清楚了
寻开心 2019-12-27
  • 打赏
  • 举报
回复
如果不用string或者其他容器类,直接用char *可以规避这个问题

这个问题发生在dll的自己模块儿的静态数据区上,动态的应该没有问题,动态的毕竟还是映射到同一个地址空间的
寻开心 2019-12-27
  • 打赏
  • 举报
回复
这个应该和静态变量的实现机制有关系,确实存在这个问题

string里面我们知道c_str()函数可以返回其包含的字符串的指针
当我们给string赋值的时候,比如 string s= “abc”;
那么abc在哪儿呢? 它是一个静态存储, 处于模块自身空间
当我们修改s的值的时候,比如 s=“23u894201y9382ur89r834ur0988r993rw0er98we9r9wr9rw9er0w”;
// 这个字符串弄长一些,短了不一定有效
就会发现s的c_str()函数返回的地址变了, 说明string确实是释放了原来的空间,而新申请了空间来管理新的字符串

因为dll是多程序之间共享的, 所以其内部是有自己的静态区
那么夸dll调用的时候, 有可能产生对静态空间的引用的问题,这个时候地址空间确实有可能不对的

64,635

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧