2

这是一个相当基本的问题,我很确定我知道答案,但是看到错误的后果是我想我应该问的一个段错误。我已经以以下方式使用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' 保留空间......至少我不认为它是。

4

2 回答 2

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, &copy);

如果您将使用 C++,您也可以将方法原型更改为:

void genericCopy(char* somestring, char*& someOtherString)

并将其称为:

genericCopy(something, copy);

然后someOtherString将作为引用传递,您分配给它的新值将传播到您的方法之外。

于 2012-07-07T05:00:28.500 回答
1

是的,你的怀疑是正确的。您应该分配一个额外的字符,并确保复制的字符串以空值结尾。(strcpy() 本身会执行此操作,但是当有人建议您切换到 strncpy() 时,他们无疑会(它更安全!)您需要格外小心,因为不能保证复制'/0'。)

但是,如果您已经在使用 C++,建议您改用 std::string。它通常是一种更简单、更不容易出错的操作字符数组的方法。

但是,这是您需要解决的进一步问题。您正在将新字符数组分配给 someOtherString 的副本。您需要进行一些更改:

void genericCopy(char *somestring, char **someOtherString) {
    *someOtherString = new char[strlen(somestring)+1];
    strcpy(*someOtherString,somestring);
    (*someOtherString)[strlen(somestring)] = '\0';
}

这样,您将在函数调用之外取回新的字符缓冲区。

于 2012-07-07T05:01:44.863 回答