这段代码有什么问题?

时间:2010-06-20 17:07:28

标签: c++

int main()
{
    char *name = new char[7];
    name = "Dolphin";
    cout << "Your name is : " << name <<endl;
    delete [] name;
}

为什么VC ++编译器不抱怨?

12 个答案:

答案 0 :(得分:14)

你有两个问题:

首先,代码有什么问题?好吧......

当您将“Dolphin”分配给名称时,您没有复制到已分配的数组中,而是将指针调整为指向字符串文字。稍后您尝试删除指针指向的内容。我希望在某些环境中可能会崩溃。

如果你真的想要一个“Dolphin”字符的副本,看一下strncpy(),但是已经观察到了,你也需要一个null的空间。

其次,为什么特定的编译器不会警告你分配是可能的:这有点困难。 [据观察,其他编译器会发出警告。]问题是这个编译器是否将字符串文字视为“指向const char的指针”或“指向char的指针”。

如果是前一种情况,那么我会发现错误。直到2004年左右,C ++在将文字视为char的指针时与C一致,因此允许赋值。所以我想你的问题是确定你正在使用哪个版本的规范,这可能取决于你正在使用的VC ++的版本以及你选择的任何编译器选项。

MSDN C ++ reference表示VC ++将字符串文字视为非const。我将把它留给VC ++大师进一步评论。

答案 1 :(得分:10)

这条线很糟糕:

name = "Dolphin";

这不是复制字符串而是重新分配指针。

所以这会导致两个问题。

  1. 你在这里释放未分配的内存delete [] name;,因为你试图释放指向文字字符串“Dolphin”的指针
  2. char *name = new char[7];中分配的内存泄露。
  3. 由于这是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)

  1. 您需要分配8个字符
  2. 您无法像这样分配字符串文字。使用const char *name = "Dolphin"(无需分配!)并且不要删除或使用strcpy将文本复制到新分配的空间中 - 稍后删除。
  3. 您无法删除驻留在只读内存中的字符串文字(“Dolphin”)。同样在那个笔记上 - 当你写name = "Dolphin"时你重新分配指针,这意味着最初分配的内存丢失了。

答案 4 :(得分:1)

  1. 您没有加入iostream,并声明您在使用cout和cin时using namespace std;
  2. 第4行有内存泄漏。name指向某个内存,如果你指定了一个字符串文字,你实际上正在为它指定一个指针,从而丢失指向前面分配的7个字节的指针, / LI>
  3. 在第6行中,你试图释放一块内存,它可能是在只读内存中,因为它是由编译器从字符串文字中准备的。你不能以标准释放这种记忆。
  4. 这样做的两种正确方法是:

    #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 ++编译器只需要“抱怨”一个不正确的程序,这个源代码不是。

该计划中的逻辑错误包括:

  1. 由行name = "Dolphin"
  2. 引起的内存泄漏
  3. 尝试在delete[]
  4. 未返回的指针上调用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