这是一个相当基本的问题,我很确定我知道答案,但是看到错误的结果是我认为我应该问的一个段错误。我一直在以下方式使用strlen()
和new char[]
运算符已经有一段时间了,只是发现了一些引发红旗的事情:
void genericCopy(char *somestring, char *someOtherString) {
someOtherString = new char[strlen(somestring)];
strcpy(someOtherString,somestring);
}
我的问题是,看到字符串应该为空终止,我应该这样做:
void genericCopy(char *somestring, char *someOtherString) {
someOtherString = new char[strlen(somestring)+1];
strcpy(someOtherString,somestring);
someOtherString[strlen(someOtherString)] = '\0';
}
到目前为止,我从未遇到过第一种方法的问题,但这并不意味着我做得对。由于strlen()
返回的长度是字符串中没有空终止符的字符数,所以new不会为'/ 0'保留空间......至少我认为不是。
答案 0 :(得分:3)
首先,你应该知道你的这个功能是没有意义的,只需使用strdup
(如果在您的系统上可用)。
但是,是的,你需要一个额外的字节来存储\0
,所以总是做new char[strlen(somestring)+1];
之类的事情。但是,无需手动添加\0
; strcpy
已经这样做了。
您应该使用类似Valgrind的内容来发现代码中的此类错误。
但是代码中还有一个问题;您的代码将始终泄漏someOtherString
;它将不会返回到您调用它的位置。您需要将方法更改为:
char *genericCopy(char *something) {
char *copy = new char[strlen(somestring)+1];
strcpy(copy,somestring);
return copy;
}
然后按如下方式获取副本:
copy = genericCopy(something);
或者您需要将方法更改为:
void genericCopy(char *something, char **copy) {
*copy = new char[strlen(somestring)+1];
strcpy(*copy,somestring);
}
并将其命名为:
genericCopy(something, ©);
如果您将使用C ++,您也可以将方法原型更改为:
void genericCopy(char* somestring, char*& someOtherString)
并将其命名为:
genericCopy(something, copy);
然后someOtherString
将作为参考传递,您分配给它的新值将传播到您的方法之外。
答案 1 :(得分:1)
是的,你的怀疑是正确的。您应该分配一个额外的字符,并确保复制的字符串以空值终止。 (strcpy()本身会这样做,但是当有人告诉你你切换到strncpy(),因为他们无疑会(它更安全!)你需要格外小心,因为它不能保证复制'/μ0'。)
但是,如果您已经在使用C ++,那么建议您切换到使用std :: string。它通常是一种更容易,更不容易出错的操作字符数组的方法。
但是,这是您需要解决的另一个问题。您将新的字符数组分配给someOtherString的COPY。你需要做一些改变:
void genericCopy(char *somestring, char **someOtherString) {
*someOtherString = new char[strlen(somestring)+1];
strcpy(*someOtherString,somestring);
(*someOtherString)[strlen(somestring)] = '\0';
}
这样你就可以在函数调用之外找回新的字符缓冲区。