int main()
{
char *name = new char[7];
name = "Dolphin";
cout << "Your name is : " << name <<endl;
delete [] name;
}
为什么VC ++编译器不抱怨?
答案 0 :(得分:14)
你有两个问题:
首先,代码有什么问题?好吧......
当您将“Dolphin”分配给名称时,您没有复制到已分配的数组中,而是将指针调整为指向字符串文字。稍后您尝试删除指针指向的内容。我希望在某些环境中可能会崩溃。
如果你真的想要一个“Dolphin”字符的副本,看一下strncpy(),但是已经观察到了,你也需要一个null的空间。
其次,为什么特定的编译器不会警告你分配是可能的:这有点困难。 [据观察,其他编译器会发出警告。]问题是这个编译器是否将字符串文字视为“指向const char的指针”或“指向char的指针”。
如果是前一种情况,那么我会发现错误。直到2004年左右,C ++在将文字视为char的指针时与C一致,因此允许赋值。所以我想你的问题是确定你正在使用哪个版本的规范,这可能取决于你正在使用的VC ++的版本以及你选择的任何编译器选项。
MSDN C ++ reference表示VC ++将字符串文字视为非const。我将把它留给VC ++大师进一步评论。
答案 1 :(得分:10)
这条线很糟糕:
name = "Dolphin";
这不是复制字符串而是重新分配指针。
所以这会导致两个问题。
delete [] name;
,因为你试图释放指向文字字符串“Dolphin”的指针char *name = new char[7];
中分配的内存泄露。由于这是C ++,您应该使用std::string
。无需手动分配或取消分配,然后获得值语义:
int main()
{
std::string name;
name = "Dolphin";
cout << "Your name is : " << name <<endl;
}
最后,如果您想要更好地理解原始指针,那么这是一个可以正常工作的代码版本。需要注意的重要事项是代码分配长度+ 1(额外+1用于终止NUL字节)并使用strcpy将数据复制到新分配的内存中:
char *strdup_via_new(const char *str)
{
char *tmp = new char[strlen(str) + 1];
strcpy(tmp, str);
return tmp;
}
int main()
{
char *name = strdup_via_new("Dolphin");
cout << "Your name is : " << name <<endl;
delete [] name;
}
答案 2 :(得分:3)
问题是你正在尝试delete
一个字符串常量,“Dolphin”。
答案 3 :(得分:2)
const char *name = "Dolphin"
(无需分配!)并且不要删除或使用strcpy
将文本复制到新分配的空间中 - 稍后删除。 您无法删除驻留在只读内存中的字符串文字(“Dolphin”)。同样在那个笔记上 - 当你写name = "Dolphin"
时你重新分配指针,这意味着最初分配的内存丢失了。
答案 4 :(得分:1)
iostream
,并声明您在使用cout和cin时using namespace std;
,name
指向某个内存,如果你指定了一个字符串文字,你实际上正在为它指定一个指针,从而丢失指向前面分配的7个字节的指针, / LI>
这样做的两种正确方法是:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char *name = new char[8];
strcpy(name, "Dolphin");
cout << "Your name is : " << name <<endl;
delete [] name;
return 0;
}
在这里,请记住,要存储“Dolphin”,您需要8个字节,1个用于NUL字符。 第二个版本(更多C ++):
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "Dolphin";
cout << "Your name is : " << name <<endl;
return 0;
}
这个不需要任何删除。
编译器没有抱怨的原因很简单,编译器不会为您检查内存泄漏。还有其他程序要做,例如valgrind。编译器也不会抱怨删除字符串文字的内存,因为它没有分析你对指针做了什么,因为你为它分配了一个字符串文字的地址,所以它不知道它没有改变从那以后。
答案 5 :(得分:1)
const char* name;
就足够了。将“Dolphin”指定给name时,指针的值会发生变化。
最后,delete[] name
是错误的。它试图删除未在堆上分配的常量char *“Dolphin”。
因此,整个代码可以读取
int main()
{
const char *name;
name = "Dolphin";
cout << "Your name is : " << name <<endl;
}
编译器没有抱怨,因为你的代码没有违反C ++的语法
答案 6 :(得分:1)
此代码存在以下问题:
name = "Dolphin";
这很好,因为它指定变量名称指向字符串常量“Dolphin”,但行:
delete [] name;
尝试删除未定义的字符串常量。
您应该使用类似std :: string的东西来处理字符串。
VC ++没有抱怨,因为它是C ++,语言希望你知道你在做什么。
“C让你很容易在脚下射击.C ++使得它变得更难,但是当你这样做时,它会吹走你的整条腿。” - Bjarne Stroustrup
答案 7 :(得分:0)
C风格的字符串必须以null结尾(“Dolphin \ 0”)。编译器会为您执行此操作,但您没有给它足够的空间。将其更改为:
char *name = new char[8];
答案 8 :(得分:0)
该作业是否专门使用new和delete来证明你知道如何?在这种情况下,您需要为null终止符节省空间并使用strcpy
。如果没有,也许你应该展示初始化?
答案 9 :(得分:0)
可能是因为VC ++认为,这就是你想要在程序中做的事情。几乎没有语法错误。好吧。可能链接器要求内存泄漏错误?
这些天编译器是否也检查逻辑?
答案 10 :(得分:0)
此源代码举例说明了格式错误的程序与具有逻辑错误的程序(导致程序错误运行的错误)之间的区别。 C ++编译器只需要“抱怨”一个不正确的程序,这个源代码不是。
该计划中的逻辑错误包括:
name = "Dolphin"
delete[]
new[]
醇>
此外,虽然您没有将"Dolphin"
复制到7-char数组中,但您似乎打算这样做。您需要注意目标分配是否包含构成字符串"Dolphin"
的{em>八个字符的空间('D'
,'o'
,'l'
,'p'
,'h'
,'i'
,'n'
和'\0'
)。
答案 11 :(得分:0)
代码有什么问题? 答:它有内存泄漏。 B.它做了一个不必要的新的
char *name = new char[7];
不需要,因为您最终要将名称分配给静态分配的字符串
name = "Dolphin";
℃。即使它实际上做了它想做的事情......它应该是char [8]而不是char [7]。这是邀请seg故障
为什么VC ++编译器没有抱怨? 编译器实际上并不打算抱怨内存泄漏和逻辑错误。
HTH