为什么我用c_str会出错的?(一定给分)
我在窗体上放了个edit控件
再放一个按钮,然后在BitBtn1Click中加入
char *a;
a=Edit1->Text.c_str();
ShowMessage(a);
然后我运行后发现弹出的对话框只显示Edit,而Edit后的1不见了,我打Edit1rs还是只显示Edit,但我打Edit1rst就会全部都显示了.
这是为什么呢,请各位帮帮忙吧.
问题点数:30、回复次数:14Top
1 楼wowboy(星仔)回复于 2001-05-19 19:41:00 得分 0
还有我如果再加一个Label,然后把代码改为
char *a;
a=Edit1->Text.c_str();
Label1->Caption=a;
ShowMessage(a);
结果会更神奇
我按一下按钮,label1上的显示是Edit1,对话框上的也是Edit1.
我再按一个按钮label1上显示的Edit后一个怪符号,对话框上的是Edit
但如果把ShowMessage(a);这一行去掉就什么事都没有了,这又是为什么呢?
Top
2 楼ALNG(?)回复于 2001-05-19 19:56:00 得分 0
不要存储AnsiString::c_str()的值, TeamB Guide.Top
3 楼ALNG(?)回复于 2001-05-19 19:58:00 得分 20
--------------------------------------------------------------------------------
The TeamB guide to avoiding common mistakes in C++Builder.
Don't store the result of AnsiString::c_str()
Examine the following code segment.
AnsiString strText = "Howdy Mr. Ditka.";
char *ptr = strText.c_str();
strText = "Goodbye Mr. Ditka";
Label1->Caption = ptr;
This code contains a serious defect. If you execute this code, you will see that the label displays the first string that was assigned to strText. This may surprise you. Why doesn't the label contain the string that says "Goodbye Mr. Ditka"? After all, doesn't ptr point to the string that is contained in the strText variable?
Whenever you assign a new string to an AnsiString variable, the AnsiString deallocates whatever memory it previously owned and allocates new memory for the new string. When the new memory is allocated, it is unlikely to be the same memory that was originally returned by the c_str function.
The second line of code in the example above stores the pointer returned by c_str for later use. After the pointer is stored, a new string is assigned to the AnsiString variable. At this point, the strText variable deallocates the first string and allocates memory for the new string. Now ptr points to memory that has been deleted. When you copy that memory into the label, you see the remnants of the original string. For larger strings, the label may contain garbage characters, or the label may appear to be truncated. De-referencing the data in the ptr variable may also cause an access violation because you are using memory that the application no longer owns.
Storing the result of c_str can lead to problems that are more difficult to track down. For example:
char *ptr1 = Edit1->Text.c_str();
char *ptr2 = Edit2->Text.c_str();
Label1->Caption = "Edit1 contains " + AnsiString(ptr1);
Label2->Caption = "Edit2 contains " + AnsiString(ptr2);
On the surface, the code looks like it should work. Sure, we store the pointer returned from c_str, but nothing is done that would cause the string to be re-allocated as in the first example. However, if you test this code, you will see that it does not work. Sometimes the labels will both display the string from the second edit box, and sometimes they contain garbage.
The problem is that the Text property of TEdit returnes a new AnsiString by value. This new AnsiString object is a temporary object. Temporary objects don't last forever. They only hang around as long as they are needed. They are destroyed before the next line of code executes.
In this code example, the temporary object is only needed for the call to c_str. Once the c_str method has been called, the temporary object is destroyed because it is no longer needed. Here is the catch. Deleting the temporary object deletes the memory that was pointed to by c_str, which means that ptr1 points to deleted memory. You can see the destruction of the temporary object by viewing the assembly code generated by these statements.
// assembly output for the statement
char *ptr1 = Edit1->Text.c_str();
mov ...
lea ...
call System::AnsiString::AnsiString(); // create temp object
mov ...
inc ...
mov ...
call Controls::TControl::GetText(); // load Caption into temp AnsiString
lea ...
call System::AnsiString::c_str() // get c_str of temp object
mov ...
dec ...
lea ...
mov ...
call System::AnsiString::~AnsiString // delete temp object
All of this code is generated by the one statement where ptr1 is assigned the value of Edit1->Text.c_str(). Before the next line of code executes, the temporary AnsiString object is destroyed. Deleting the temporary AnsiString object renders the previous c_str result worthless, and that is exactly what happens (and it's exactly what should happen, the compiler is obeying the standard by cleaning up temporary objects in this manner).
The moral of this story is to avoid saving the result from AnsiString::c_str because you run the risk of keeping a pointer to memory that has been de-allocated.
Top
4 楼cker(〖烟波浩淼三千里、人鬼殊途五百年〗)回复于 2001-05-19 21:23:00 得分 5
char a[255];
strcpy(a,Edit1->Text.c_str());
....Top
5 楼leejd(小东)回复于 2001-05-19 22:00:00 得分 0
同意楼上的,char类型的字符串只能用来拷贝的,不能直接赋值Top
6 楼songhtao(三十年孤独)回复于 2001-05-19 22:01:00 得分 0
我的正常Top
7 楼SAsura(爱我别走)回复于 2001-05-19 23:05:00 得分 5
ShowMessage接受的参数是AnsiString,为什么要转成char *再传给他?
AnsiString::c_str()返回的指针只有暂时的意义
重分配字符串长度后地址很可能改变。Top
8 楼wowboy(星仔)回复于 2001-05-19 23:09:00 得分 0
我现在也正常了,但我平时见好多人都这么写的,难道都错了。
正如啊良说的用指针指向一个已释放的内存是个好大的漏洞。
那么我想问怎么平时见好多人都这么写的,都不对吗?
还有啊良,什么是TeamB guide 好像蛮好的。Top
9 楼tlc97(文风)回复于 2001-05-19 23:19:00 得分 0
borland 的社区有很多这样的贴子Top
10 楼wowboy(星仔)回复于 2001-05-20 13:25:00 得分 0
我要把这个问题移回到CB版。Top
11 楼wowboy(星仔)回复于 2001-05-21 17:18:00 得分 0
给分.Top
12 楼comanche(太可怕)回复于 2001-05-21 17:36:00 得分 0
这样写没什么问题,但不知道你为什么这样???!!
TeamB是Borland news group 上一个著名小组,主要成员是 Borland公司VCL开发都和一些自愿的程序员(都很猛),不过跟他们交流后发现,原来他们也常放错..哈哈
Top
13 楼comanche(太可怕)回复于 2001-05-21 17:39:00 得分 0
楼上的 ALNG(GNLA)说得也没错,但关下面代码不正确的原因在
AnsiString strText = "Howdy Mr. Ditka.";
char *ptr = strText.c_str();
strText = "Goodbye Mr. Ditka"; // 这一句 AnsiString重新分配了内存,存
// 因为它比原来的大
Label1->Caption = ptr;
Top
14 楼wowboy(星仔)回复于 2001-05-26 18:13:00 得分 0
谢谢comanche(太可怕),可惜已经加分了^_^.
不过还是你感谢你的热心,下次给你加多点。
我的分数好少,所以。。。Top




