1

我正在尝试附加两个字符,但由于某种原因,我遇到了分段错误。

我的代码是这样的;

#include <string.h>
char *one = (char*)("one");
char *two = (char*)("two");

strcat(one, two);

而且我似乎遇到了分段错误strcat(one, two),这是为什么呢?

4

9 回答 9

5

http://www.cplusplus.com/reference/clibrary/cstring/strcat/

strcat 的第一个参数必须足够大以容纳结果字符串

尝试:

//assuming a,b are char*
char* sum = new char[strlen(a) +strlen(b)+1];
strcpy(sum,a);
strcat(sum,b);
于 2011-02-13T21:34:15.607 回答
3

应该有足够的合法内存来保存整个字符串。

char *one = new char[128]; //allocating enough memory!
const char *two = "two"; //"two" is const char*

strcpy(one, "one");
strcat(one, two); //now the variable "one" has enough memory to hold the entire string

顺便说一句,如果你更喜欢在 C++ 中使用std::stringover char*,这样的事情会更容易处理:

#include<string>

std::string one = "one";
std::string two = "two";

one = one + two; //Concatenate 

std::cout << one;

输出:

onetwo
于 2011-02-13T21:34:28.673 回答
2

段错误是因为您尝试写入只读内存。strcat 的第一个动作是将“t”从两个的第一个条目复制到“一个”末尾的空值中。所以严格来说,seg 错误并不是由于缺乏存储空间——我们从来没有走到那一步。事实上,这段代码也可能会给你一个段错误:

char* one = "one";
char* two = "";
strcat(one, two);    

所有这一切都试图做的是在一个空值上复制一个空值,但在只读内存中。我想优化器可能会在某些平台上阻止这种情况。

奇怪的是,以下(不正确的)代码(可能)不会给你一个段错误,甚至给出“正确”的答案:

char one[] = "one";
char two[] = "two";
strcat(one, two);   
printf("%s\n", one);

这成功地将“onetwo”写入我机器上的标准输出。我们得到一个堆栈涂鸦,我们碰巧逃脱了。

另一方面,这确实有段错误:

char* one = "one        "; // Plenty of storage, but not writable.
char two[] = "two";
strcat(one,two);    

因此解决方案:

const unsigned enoughSpace = 32;
char one[enoughSpace] = "one";
char two[] = "two";
strcat(one,two);    
printf("%s\n", one);

这个问题当然是,为了存储即将到来的东西,要制造足够大的空间吗?

因此函数 strncat 或 strcat_s 或更简单的 std::string。

故事的寓意:在 C++ 中,就像 C 一样,你真的需要知道你的内存布局是什么。

于 2011-02-13T22:48:32.930 回答
2

有两个原因。

  1. 如果您将指针初始化为字符串文字,则该内存是只读的,修改它会导致未定义的行为。在这种情况下,如果您尝试将字符串附加到字符串文字,您将修改这种内存,这将导致问题。

  2. 使用 strcat 时,您需要保证在您指定的位置存在用于连接字符串的空间。在这种情况下,您不能保证这一点,因为字符串文字只能保证有足够的空间来保存文字本身。

要解决此问题,您需要显式分配一个足够大的缓冲区来容纳两个字符串的连接,包括空终止符。这是一种方法:

char* buffer = malloc(strlen(one) + strlen(two) + 1);
strcpy(buffer, one);
strcat(buffer, two);

希望这可以帮助!

于 2011-02-13T21:35:20.037 回答
1

这里有几个问题。首先,尽管您已将字符串转换为可变版本,但它们确实是字符串文字,因此不应写入。其次,您正在使用strcat它将写入字符串缓冲区,完全忽略字符串缓冲区的长度(最好使用strncat,它需要您指定缓冲区的长度)。最后,由于这是 C++,最好使用:

#include <string>

// ...

string one = "one";
string two = "two";
one.append(two); 
于 2011-02-13T21:36:56.293 回答
1

你从来没有为你的字符串保留一些空间。

#include <string.h>
#include <stdio.h>

int main(void){
    char str[20] = "";
    strcat(str, "one");
    strcat(str, "two");
    printf("%s", str);
}

将是一种正确的方法来做到这一点。另一个(更好的方式)是使用std::string类。

#include <string>
#include <cstdio>

int main(void){
    std::string str;
    str += "one";
    str += "two";
    std::printf("%s", str.c_str());
}
于 2011-02-13T21:34:52.923 回答
0

您的目标字符串应该足够大以容纳目标字符串和源字符串。所以一个例子是

char one[10] = "one";
char two[4] = "two";
strcat(one,two);

于 2011-02-13T21:36:54.637 回答
0

strcat需要一个“可写”缓冲区作为目标。在您的示例中,它是指向您无法写入的字符串常量(或文字)的指针,因此会导致异常。目标缓冲区可以是堆栈上的缓冲区或动态分配的缓冲区(例如,使用 malloc)。

于 2011-02-13T21:34:39.143 回答
0

这不是“空间不够”的问题。

char *a = "str";

看上面的代码,指针a是指向“静态内存”的。字符串“str”存储在PCB中的静态位置,这意味着它不能被覆盖。

所以,下面的代码会更好:

#include <string>
using std::string;

string a = "stra";
string b = "strb";

a += b;
于 2011-02-14T04:46:01.190 回答