C语言 当 strlen 产生分段错误时,来自 GetString() 的 C 字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15892003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C string from GetString() when strlen produces segmentation fault
提问by IberoMedia
I am running a program in C. When I run the program I get a segmentation fault error. IN gdb when I backtrace it tells me
我正在用 C 运行一个程序。当我运行该程序时,我收到一个分段错误错误。当我回溯时,在 gdb 中它告诉我
Program received signal SIGSEGV, Segmentation fault. __strlen_sse2_bsf () at ../sysdeps/i386/i686/multiarch/strlen-sse2-bsf.S:51 51 movdqu (%edi), %xmm1
程序收到信号 SIGSEGV,分段错误。__strlen_sse2_bsf () at ../sysdeps/i386/i686/multiarch/strlen-sse2-bsf.S:51 51 movdqu (%edi), %xmm1
I believe it has to do with strlen.
我相信这与strlen有关。
The only time I use strlen is:
我唯一使用 strlen 的时间是:
string s = GetString();
int stringlength = strlen(s);
When I change strlen for sizeof error stops.
当我为 sizeof 更改 strlen 时,错误停止。
What is wrong with my code?
我的代码有什么问题?
Documentation of GetString
GetString 的文档
/*
* Reads a line of text from standard input and returns it as a
* string (char *), sans trailing newline character. (Ergo, if
* user inputs only "\n", returns "" not NULL.) Returns NULL
* upon error or no input whatsoever (i.e., just EOF). Leading
* and trailing whitespace is not ignored. Stores string on heap
* (via malloc); memory must be freed by caller to avoid leak.
*/
string GetString(void) {
// growable buffer for chars
string buffer = NULL;
// capacity of buffer
unsigned int capacity = 0;
// number of chars actually in buffer
unsigned int n = 0;
// character read or EOF
int c;
// iteratively get chars from standard input
while ((c = fgetc(stdin)) != '\n' && c != EOF)
{
// grow buffer if necessary
if (n + 1 > capacity)
{
// determine new capacity: start at 32 then double
if (capacity == 0)
capacity = 32;
else if (capacity <= (UINT_MAX / 2))
capacity *= 2;
else
{
free(buffer);
return NULL;
}
// extend buffer's capacity
string temp = realloc(buffer, capacity * sizeof(char));
if (temp == NULL)
{
free(buffer);
return NULL;
}
buffer = temp;
}
// append current character to buffer
buffer[n++] = c;
}
// return NULL if user provided no input
if (n == 0 && c == EOF)
return NULL;
// minimize buffer
string minimal = malloc((n + 1) * sizeof(char));
strncpy(minimal, buffer, n);
free(buffer);
// terminate string
minimal[n] = 'string s = GetString();
int stringlength = 0;
if (s != 0)
stringlength = strlen(s);
';
// return string
return minimal;
}
回答by Jonathan Leffler
The description of the getString()function clearly states that it can return NULL on an error or on EOF.
该getString()函数的描述清楚地表明它可以在出现错误或 EOF 时返回 NULL。
If you pass the return value to strlen()without checking, your program will crash.
如果您将返回值传递给strlen()没有检查,您的程序将崩溃。
// minimize buffer
string minimal = malloc((n + 1) * sizeof(char));
strncpy(minimal, buffer, n);
free(buffer);
This at least won't crash.
这至少不会崩溃。
You might also notice how much confusion the typedef char *string;causes and how little benefit it confers, and take it to heart. You don't have to repeat the mistakes of those who are teaching you.
您可能还会注意到typedef char *string;原因有多少混乱以及它带来的好处有多少,并将其牢记在心。你不必重复那些教你的人的错误。
I also observe that the code fragment:
我还观察到代码片段:
string minimal = realloc(buffer, n + 1);
could be better, and more simply, written as:
可以更好,更简单地写成:
##代码##to shrink the allocation to the correct size.
将分配缩小到正确的大小。

