17

谁能告诉我我在这里做错了什么?为什么我的程序会出现段错误?我正在尝试在string1and之间插入第三个字符串string2

#include <stdio.h>

int main (void) 
{
char *string1 = "HELLO";
char *string2 = "WORLD";
char *stringX  = "++++";
char *string3;
printf ("%s,%s\n",string1,string2);
sprintf(string3,"%s%s%s",string1,stringX,string2);
printf ("NewVar: %s",string3);
}

为什么不sprintf将结果值存储在 指向的内存地址string3?它在我声明string3为普通数组时有效,但在它是指向char数组的指针时无效。

我以为string3没有指向任何内存位置,但是当我这样做时似乎确实如此printf("%p",string3);

输出:

# ./concat
HELLO,WORLD,0x40042
4

5 回答 5

36

想象一下,你有一堆现金要放在公文包里。你需要什么?您必须测量现金的大小才能知道要使用多大的公文包,并且您需要一个把手来方便地携带现金。

现金就是你的琴弦。公文包是内存空间。公文包手柄是指针。

  1. 衡量你的现金:strlen(string1) + strlen(string2) + strlen(stringX)。将此称为“总数”。
  2. 现在得到一个足够大的公文包:malloc(total+1)
  3. 并对其进行处理:string3

将所有这些拼凑在一起...

char *string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
sprintf(string3, "%s%s%s", string1, stringX, string2);

那么第一次尝试有什么问题呢?你没有公文包。你有现金,有把手,但中间没有公文包。它似乎以一种随机的方式起作用,因为编译器给了你一个肮脏的垃圾箱来存放现金。有时垃圾箱有空间,有时没有。如果没有,我们称之为“分段错误”。

只要有数据,就必须为该数据分配空间。编译器为常量字符串分配空间,例如"HELLO". 但是您必须为运行时构建的字符串分配空间。

于 2013-11-04T16:51:05.320 回答
10

sprintf确实将值存储在那里。问题是指针 string3 具有未初始化的值,因此您只是在覆盖随机内存。

您拥有的一种选择是使用静态字符串缓冲区:

char string3[20];
snprintf(string3, sizeof(string3), "Hello!");

或者,您可以asprintf在基于 GNU libc 的系统上使用自动分配适当的空间:

char * string3;
asprintf(&string3, "Hello!");
// ... after use
free(string3); // free the allocated memory
于 2013-11-04T16:49:30.623 回答
8

sprintf不为其写入的字符串分配内存。您必须提供一个有效的字符串才能写入,但目前正在向它传递一个未初始化的指针。

最简单的解决方法是更改

char *string3;
sprintf(string3,"%s%s%s",string1,stringX,string2);

char string3[200];
sprintf(string3,"%s%s%s",string1,stringX,string2);

snprintf在这种情况下,您可能希望通过使用来防止缓冲区溢出

char string3[200];
snprintf(string3,sizeof(string3),"%s%s%s",string1,stringX,string2);

或者,您也可以通过在运行时确定大小来处理更大长度的源字符串,并在完成后string3注意free此内存。

char* string3 = malloc(strlen(string1) + strlen(stringX) + strlen(string2) + 1);
if (string3 == NULL) {
    // handle out of memory
}
sprintf(string3,"%s%s%s",string1,stringX,string2);
...
free(string3);
于 2013-11-04T16:48:08.007 回答
4

如果您需要将其放在堆上,则需要为其分配空间string3malloc如果不需要,则将其声明为字符数组。

于 2013-11-04T16:47:16.700 回答
0

假设您定义iint i; 在这个级别中,您告诉我将存储,但变量integer number中仍然没有有意义的数字。i像这样在定义char *string3时告诉您string3将存储 char 指针,但仍然没有有意义的地址。所以你必须为这个变量分配内存

string3 =  malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
于 2020-07-04T07:27:21.363 回答