附加两个字符时的分段错误 - C ++

时间:2011-02-13 21:30:22

标签: c++ linux segmentation-fault append chars

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

我的代码就像;

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

strcat(one, two);

我似乎在strcat(one, two)遇到了分段错误,为什么会这样?

9 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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::string而不是char*,那么这样的事情会更容易处理:

#include<string>

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

one = one + two; //Concatenate 

std::cout << one;

输出:

onetwo

答案 2 :(得分:2)

这有两个原因。

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

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

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

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

    希望这有帮助!

答案 3 :(得分:2)

seg错误是因为您尝试写入只读内存。 strcat的第一个动作是将't'从第一个条目2复制到“one”结尾处的null。严格来说,seg故障不是由于缺乏存储 - 我们从来没有这么做过。事实上,这段代码也可能会给你一个seg错误:

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

所有这些尝试都是在null上复制null,但是在只读内存中。我想一个优化器可能会在某些平台上阻止它。

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

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

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

另一方面,这确实是一个错误:

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一样,你真的需要知道你的内存布局是什么。

答案 4 :(得分: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());
}

答案 5 :(得分:1)

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

#include <string>

// ...

string one = "one";
string two = "two";
one.append(two); 

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

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

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

答案 8 :(得分:0)

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

char *a = "str";

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

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

#include <string>
using std::string;

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

a += b;