添加两个字符-C++时的分割错误

添加两个字符-C++时的分割错误,c++,linux,segmentation-fault,append,chars,C++,Linux,Segmentation Fault,Append,Chars,我试图附加两个字符,但由于某种原因,我得到了一个分段错误 我的代码是这样的 #include <string.h> char *one = (char*)("one"); char *two = (char*)("two"); strcat(one, two); 我似乎在strcatone中遇到了一个分割错误,2,为什么 strcat的第一个参数必须足够大,以容纳生成的字符串 尝试: strcat的第一个参数必须足够大,以容纳生成的字符串 尝试: 应该有足够的合法内存来保存整个字

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

我的代码是这样的

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

strcat(one, two);
我似乎在strcatone中遇到了一个分割错误,2,为什么

strcat的第一个参数必须足够大,以容纳生成的字符串

尝试:

strcat的第一个参数必须足够大,以容纳生成的字符串

尝试:


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

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::Ctrase*Ctring,这样的事情就更容易处理:

#include<string>

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

one = one + two; //Concatenate 

std::cout << one;

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

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::Ctrase*Ctring,这样的事情就更容易处理:

#include<string>

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

one = one + two; //Concatenate 

std::cout << one;

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

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

您从未为字符串保留过一些空间

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

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

您从未为字符串保留过一些空间

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

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

这有两个原因

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

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

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

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

希望这有帮助

这有两个原因

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

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

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

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

希望这有帮助

目标字符串应足够大,以容纳目标字符串和源字符串。例如


目标字符串应足够大,以容纳目标字符串和源字符串。例如


这里有几个问题。首先,尽管您已将字符串强制转换为可变版本,但它们实际上是字符串文本,因此不应写入。其次,您使用的是将写入字符串缓冲区的,完全忽略字符串缓冲区的长度。最好使用它,它要求您指定缓冲区的长度。最后,由于这是C++,使用它的方式更好:

#include <string>

// ...

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

这里有几个问题。首先,尽管您已将字符串强制转换为可变版本,但它们实际上是字符串文本,因此不应写入。其次,您使用的是将写入字符串缓冲区的,完全忽略字符串缓冲区的长度。最好使用它,它要求您指定缓冲区的长度。最后,由于这是C++,使用它的方式更好:

#include <string>

// ...

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

seg故障是因为您试图写入只读存储器。strcat的第一个操作是将“t”从两个的第一个条目复制到一个末尾的null中。因此,严格来说,seg故障不是由于存储不足造成的——我们从来没有做到这一点。事实上,此代码也可能导致seg故障:

char* one = "one";
char* two = "";
strcat(one, two);    
char* one = "one        "; // Plenty of storage, but not writable.
char two[] = "two";
strcat(one,two);    
所有这些尝试都是将null复制到null上,但复制到只读内存中。我想乐观主义者可能会碰巧在某些平台上阻止这一点

奇怪的是,以下错误代码可能不会为您提供seg故障,甚至不会给出正确答案:

char one[] = "one";
char two[] = "two";
strcat(one, two);   
printf("%s\n", one);
这将成功地将OneTo写入我机器上的标准输出。我们得到了一堆乱涂乱画的东西,而我们恰好侥幸逃脱了

另一方面,这不会导致seg故障:

char* one = "one";
char* two = "";
strcat(one, two);    
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);
当然,这个问题是,在o中创建足够大的空间 为了储存即将到来的一切

因此,函数strncat,或strcat_s,或者更容易使用std::string


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

< P> SEG错误是因为你试图写只读内存。strcat的第一个操作是将“t”从两个的第一个条目复制到一个末尾的null中。因此,严格来说,seg故障不是由于存储不足造成的——我们从来没有做到这一点。事实上,此代码也可能导致seg故障:

char* one = "one";
char* two = "";
strcat(one, two);    
char* one = "one        "; // Plenty of storage, but not writable.
char two[] = "two";
strcat(one,two);    
所有这些尝试都是将null复制到null上,但复制到只读内存中。我想乐观主义者可能会碰巧在某些平台上阻止这一点

奇怪的是,以下错误代码可能不会为您提供seg故障,甚至不会给出正确答案:

char one[] = "one";
char two[] = "two";
strcat(one, two);   
printf("%s\n", one);
这将成功地将OneTo写入我机器上的标准输出。我们得到了一堆乱涂乱画的东西,而我们恰好侥幸逃脱了

另一方面,这不会导致seg故障:

char* one = "one";
char* two = "";
strcat(one, two);    
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


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

< P>这不是没有足够空间的问题。
char *a = "str";
看看上面的代码,指针是指向静态内存的。字符串str存储在PCB中的静态位置,这意味着它不能被覆盖

因此,以下代码会更好:

#include <string>
using std::string;

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

a += b;

这不是空间不够的问题

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

因此,以下代码会更好:

#include <string>
using std::string;

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

a += b;


调用strcat之前,内存布局是什么样子的?您希望它以后会是什么样子?决不能盲目地执行强制转换,在这种情况下应该删除强制转换,因为您应该启用从字符串文字到非常量字符指针的强制转换。该警告将引导您朝着正确的方向解决此问题,下面的答案中多次给出了此警告。调用strcat之前,内存布局可能会重复吗?您希望它以后会是什么样子?决不能盲目地执行强制转换,在这种情况下应该删除强制转换,因为您应该启用从字符串文字到非常量字符指针的强制转换。该警告将引导您朝着正确的方向解决此问题,下面的答案中多次给出了此警告。正确解释的可能重复。但是,应该提倡使用strncat/strncpy和std::string。这是个糟糕的例子。这里不需要动态分配:char one[128]=1;史崔通,二号;。为什么不在后面的std::string示例中使用1+=2?@Fred:OP似乎是新手;这就是为什么我把它简单明了@弗雷德:如果你不喜欢,就给我一票否决票。我不想争论这些编码风格和用法。我不会用char*作为字符串的开头。所以请饶了我吧!教某人,特别是新手,不必要地使用动态分配总是一个坏例子。使用比绝对需要的字符缓冲区稍大一点的字符缓冲区是不可能的。很好的解释。但是,应该提倡使用strncat/strncpy和std::string。这是个糟糕的例子。这里不需要动态分配:char one[128]=1;史崔通,二号;。为什么不在后面的std::string示例中使用1+=2?@Fred:OP似乎是新手;这就是为什么我把它简单明了@弗雷德:如果你不喜欢,就给我一票否决票。我不想争论这些编码风格和用法。我不会用char*作为字符串的开头。所以请饶了我吧!教某人,特别是新手,不必要地使用动态分配总是一个坏例子。使用一个稍微大于绝对要求的字符缓冲区甚至不在同一个范围内。为什么在第一个例子中使用指令?@米迦勒:我前面的C头C的C++版本包括在结尾,而不是。可以说这是一种习惯;为什么不把using指令放在函数范围内?@Fred:好问题,我从来没有想过。我只在.cpp文件中使用using指令,回想起来,我总是将它们放在全局范围内。。有什么理由我应该改变这个习惯吗?@Xeo:使用指令通常会导致一些问题,习惯性地将它们的效果本地化会使问题更容易解决。例如,std::endl和Qt有一个问题。在这种情况下,像Bo Persson一样,我只需键入STD::两次。为什么在第一个例子中使用指令?@米迦勒:我前面的C头C的C++版本包括在结尾,而不是。可以说这是一种习惯;为什么不把using指令放在函数范围内?@Fred:好问题,我从来没有想过。我只在.cpp文件中使用using指令,回想起来,我总是将它们放在全局范围内。。有什么理由我应该改变吗
在habbit?@Xeo:使用指令通常会导致一些问题,习惯性地将其效果本地化会使问题更容易解决。例如,std::endl和Qt存在一个问题。在本例中,与Bo Persson一样,我只需键入std::两次,而不是对两个字符进行计数,而是让编译器为您执行:char two[]=two;。让编译器为您计算:char two[]=two;,而不是为两个字符计数;。