在C中复制字符串时,为空终止字符分配空间?

时间:2009-10-17 03:46:38

标签: c++ c cstring

const char * src =“hello”;

调用strlen(src);返回大小为5 ...

现在说我这样做:

char* dest = new char[strlen(src)];
strcpy(dest, src);

这似乎不应该有效,但是当我输出一切看起来是对的。好像我最后没有为空终结器分配空间......这是对的吗?感谢

8 个答案:

答案 0 :(得分:13)

你没有为终结器分配空间是正确的,然而如果不这样做,则不一定会导致程序失败。您可能会覆盖堆上的以下信息,或者您的堆管理器将分配大小四舍五入到16个字节的倍数,因此您不一定会看到此错误的任何可见效果。

如果您在Valgrind或其他堆调试器下运行程序,则可能能够更快地检测到此问题。

答案 1 :(得分:11)

是的,你应该至少分配strlen(src)+1个字符。

答案 2 :(得分:7)

  

这似乎不应该起作用,但是当我输出它看起来正确的一切时。

欢迎来到未定义行为的世界。当你这样做时,任何事情都可能发生。您的程序可能崩溃,您的计算机可能崩溃,您的计算机可能会爆炸,demons can fly out of your nose

最糟糕的是,你的程序可以运行得很好,不显眼地看起来它正常工作,直到有一天它开始吐出垃圾,因为它覆盖了某处的敏感数据,因为在某个地方,有人为他们分配了一个太少的字符数组,现在你已经损坏了堆,并且在一百万英里之外的某个时刻你会遇到一个段错误,甚至更糟糕的是你的程序很快就会被破坏的堆堆积而且你的功能在损坏的信用卡号码上运行而你会变得很大麻烦。

即使它看起来有效,但事实并非如此。这是未定义的行为。避免使用它,因为你永远无法确定它会做什么,即使你在尝试它时它做了什么也没关系,它可能在另一个平台上没有问题。

答案 3 :(得分:3)

我读过的最好的描述(在stackoverflow上)并且像这样:

如果速度限制是50而你的车速是60.你可能会很幸运而没有得到机票,但有一天可能不是今天也许不是明天,而是有一天警察会等你。在那一天,你将支付,你将付出高昂的代价。

如果有人能找到原文,我宁愿指出它们比我的解释更有说服力。

答案 4 :(得分:2)

strcpy将复制空终止的char以及所有其他字符。

因此,您将hello + 1的长度(即6)复制到缓冲区大小为5。

虽然这里有一个缓冲区溢出,但是不是你自己的内存将会有未定义的结果。

答案 5 :(得分:1)

或者,您也可以使用dest = strdup(src),它将为字符串+ 1分配足够的内存以用于空终止符(对于Juliano的答案为+1)。

答案 6 :(得分:1)

这就是为什么你总是应该总是在任何看起来有效的C程序上运行valgrind

答案 7 :(得分:1)

是的,每个人都涵盖了重点;你不能保证失败。事实是,空终止符通常为0,0是一个非常常见的值,可以放在任何特定的内存地址中。所以它恰好工作。您可以通过获取一组内存,向其中写入一堆垃圾然后在那里编写该字符串并尝试使用它来测试这一点。

无论如何,我在这里看到的主要问题是你在谈论C但你有这行代码:

char* dest = new char[strlen(src)];

这不会在任何标准C编译器中编译。 C中没有new个关键字。那就是C ++。在C中,您将使用其中一个内存分配函数,通常为malloc。我知道这似乎是一种错误,但实际上,它不是。