为什么我要执行此代码的细分故障?
我试图找出这段代码的问题:
int main(int argc, char *argv[])
{
char *s;
scanf("%s\n", s);
char *t = malloc(sizeof(*s) + 1);
strcpy(t, s);
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
free(t);
return 0;
}
我试图将输入的第一个字母大写,例如将 hi!
更改为 Hi!
。
I'm trying to figure out the issue with this code:
int main(int argc, char *argv[])
{
char *s;
scanf("%s\n", s);
char *t = malloc(sizeof(*s) + 1);
strcpy(t, s);
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
free(t);
return 0;
}
I was trying to upper case the first alphabet of my input to get for example hi!
changed into Hi!
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您在char*上使用scanf,而无需先分配内存。这可能会导致细分故障。实际上,以下代码:
有时确实会出现分割故障。取而代之的是,如果要避免
malloc
,则可以使用char
数组而不是char*
。您可以使用fgets
而不是scanf
来防止写入界限,也可以使用scanf
本身来检查:在您的代码中,在
%s
之后,您在scanf
语句中有一个\ n
, 't打算这种行为)。您可以在此处查看它的作用:其次,在为
t
分配内存时,您使用的是sizeof(*s)
,它只是size> sizeof(char)
定义为1
。相反,您应该使用strlen(s)+1
,它将分配一个字节,而不是s的长度。另外,还建议检查t == null
。在调用
之前在平台上签名。有关此答案的更多信息: https://stackoverflow.com/a/21805970/18639286 (尽管问题是一个C ++问题,答案实际上引用C标准规格)
我已将上述更改编辑为您的代码以获取以下内容:
一些额外的积分:
您也可以使用
fgets
而不是scanf
:fgets(S,100,STDIN);
作为fgets
确实绑定了检查。另外,fgets读取直到线/文件的结尾或缓冲区已满,因此它将通过输入中的空格读取,但是
scanf
将停止在空间。或正如Ted Lyngmo在评论中指出的那样,scanf
带有%s
读取一个单词,而fgets
读取一行。但是,即使您打算只读一个单词,也可以使用
fgets
,然后使用sscanf
来读取使用fgets的字符串中的第一个单词
。示例:在这里,您不需要使用
%19S
,因为我们知道buffer
的大小。You are using scanf on a char* without first allocating memory to it. This may lead to segmentation fault. In fact, the following code :
does give segmentation fault sometimes. Instead you can use a
char
array instead of achar*
if you want to avoidmalloc
beforescanf
. You can usefgets
instead ofscanf
to prevent writing out of bounds or you can check withscanf
itself like this:Also in your code, you have a
\n
after%s
in thescanf
statement, that I have removed(assuming you didn't intend this behaviour) . You can see what that does here: Using "\n" in scanf() in CSecondly, in allocating memory for
t
, you are usingsizeof(*s)
which is justsizeof(char)
which is defined to be1
. Instead, you should be usingstrlen(s)+1
which will allocate one more byte than the length of s which should work fine. Also, checking ift==NULL
is also recommended.Before calling
toupper
the argument must be type-casted into anunsigned char
to avoid the risks of undefined behaviour if thechar
type is signed on the platform. More on this can be found on this answer: https://stackoverflow.com/a/21805970/18639286 (Though the question was a C++ question, the answer actually quotes C standard specifications)I have edited the above changes into your code to get the following:
Some extra points:
You can also use
fgets
instead ofscanf
:fgets(s, 100, stdin);
asfgets
does bound checking.Also, fgets reads till end of line/file or till the buffer is full, so it will read past the spaces in input, But
scanf
will stop at a space. Or as Ted Lyngmo pointed out in the comments,scanf
with%s
reads a word, whilefgets
reads a line.But, even if you intend to read only a word, you can use
fgets
and then usesscanf
to read the first word from the string with which you usedfgets
. Example:Here, you don't need to use
%19s
because we know the size ofbuffer
.作为已经很棒的答案的旁注,我必须推荐GNU调试器(不久GDB)。
运行
“ gdb [program name]”
,该程序应与-G
flag一起编译。在交互式环境中,您可以通过键入r
来运行该程序,该程序可能会产生一些有用的信息。键入“ b< number>“
在运行时指定休息时间,然后键入“ s [number]”
程序中的许多行。GDB有很多方法可以提取有关跑步程序的信息,我建议大量建议阅读其中的文档。
As a sidenote to the already great answer, I must recommend GNU Debugger (shortly gdb).
Run
"gdb [program name]"
, the program should be compiled with the-g
flag. In the interactive environment, you can run that program by typingr
which may yield some useful information. Typing"b <number>"
to specify a break in the runtime, then type"s [number]"
a number of lines ahead in the program.There are plenty of ways with gdb to extract information about the running program, I'd heavily recommend reading the docs on it.