我是C的初学者。这是一个简单的程序,提示键盘输入名称,使用名称创建问候语,然后打印它。在运行时,在控制台输入名称并按Enter后立即发生分段故障。调试后我怀疑故障在于scanf()函数。我试过调整这个论点' name'用' *'和'&',并初始化char数组' name'用一个空字符串,但没有一个帮助。
display.blit(pygame.transform.scale(renderLayer,display.get_size()),(0,0))
pygame.display.flip()
clock.tick()
print(clock.get_fps())
答案 0 :(得分:2)
两次拨打strcat()
char *greeting;
char *suffix;
greeting = "Hello, ";
suffix = ", nice to meet you!";
strcat(greeting, name);
strcat(greeting, suffix);
通过尝试追加属于"字符串" -literal("Hello, "
)的存储来激发未定义的行为。
A"字符串" -literal的存储
要解决此问题,请提供足够大的缓冲区,并在其中复制所需的所有内容:
char *greeting;
char *suffix;
greeting = "Hello, ";
suffix = ", nice to meet you!";
char buffer[7 + 20 + 19 + 1]; /* 7 for "Hello, ",
20 for name (which in fact for your code needed to be 19 only),
19 for ", nice to meet you!" and
1 for the 0-terminator. */
strcpy(buffer, greeting); /* Use strcpy() to copy to an uninitialised buffer. */
strcat(buffer, name);
strcat(buffer, suffix);
另外,为了确保用户不会溢出为name
提供的内存,请告诉scanf()
可用的内容;
char name[20 + 1]; /* If you need 20 characters, define 1 more to hold the
"string"'s 0-terminator. */
scanf("%20s", name); /* Tell scanf() to read in a maximum of 20 chars. */
答案 1 :(得分:1)
strcat(greeting, name);
对strcat
的此次调用正在修改一个字符串常量 - 这是不合法的,这是导致您的段错误的原因(技术上,您所看到的是未定义行为的结果)。
为了完整性:
scanf("%s", name);
如果缓冲区的大小限制为20,那么您应该使用:
scanf("%19s", name);
...限制实际存储的字符数(尽管有更好的方法来读取可变长度的行)。我使用了19因为nul终结符需要空间。
然后,为您的完整字符串分配合适的存储空间:
char full_greeting[20 + 7 + 19] = ""; // name + "hello"... + "nice to meet"...
复制到那个:
strcpy(full_greeting, greeting);
strcat(full_greeting, name);
strcat(full_greeting, suffix);
printf("%s", full_greeting);
动态字符串解决方案(POSIX)
在POSIX系统上,您可以让scanf为其读取的名称分配缓冲区:
char *name = NULL;
scanf("%ms", &name); // you could also use 'getline' function
if (name == NULL) {
exit(1); // scanf failed or memory allocation failed
}
(请注意,使用getline
会读取整行,这与当前scanf
不同,后者读取第一个空格的字符串。
然后,您动态计算缓冲区的长度:
int req_len = strlen(name) + strlen(greeting) + strlen(suffix) + 1;
// (+1 is for nul terminator)
char * buffer = malloc(req_len);
if (buffer == NULL) {
exit(1); // or handle the error somehow
}
strcpy(buffer, greeting);
strcat(buffer, name);
strcat(buffer, suffix);
printf("%s", buffer);
free(buffer);
free(name);
答案 2 :(得分:1)
问题在于
strcat(greeting, name);
greeting
指向read-only
内存。将name
附加到greeting
会尝试更改其中的内容。结果是段错误。
答案 3 :(得分:0)
char *greeting;
char *suffix;
greeting = "Hello, ";
suffix = ", nice to meet you!";
strcat(greeting, name);
strcat(greeting, suffix);
当目的地不仅不可修改,而且太小时,您正在制作strcat
。你可能知道写作
char *p = "hello";
*p = 'x';
是未定义的行为。这是strcat
对您传入的greeting
参数所做的操作。解决方案是
#define MAXBUF 64
char *mystrcat(char *dest, char *src)
{
while (*dest)
dest++;
while (*dest++ = *src++)
;
return --dest;
}
char greeting[MAXBUF], *p;
strcpy(greeting, "hello, ");
p = mystrcat(greeting, name);
mystrcat(p, ", nice to meet you");
另外,请注意新功能mystrcat
。这是Joel Spolsky's famous post中解释的优化。