我正在关注K& R.在第1章末尾,提议的练习之一是编写文本包装程序。这是我写的代码:
#include <stdio.h>
#define MAXLINE 1000
#define WRAP 10
int getl(char s[]);
void wrap(char s[], int l);
/* wrap.c: wraps text */
main ()
{
char line[MAXLINE];
int c;
while ((c = getl(line)) >= 0)
wrap(line, c);
return 0;
}
int getl(char s[])
{
int i, c;
for (i = 0; (c = getchar()) != '\n' && c != EOF && i < MAXLINE; ++i)
s[i] = c;
s[i] = '\n';
if (c == EOF)
i = -1;
return i;
}
void wrap(char s[], int l)
{
int i = 1,ii, c;
if (l == 0)
putchar('\n');
for(c = 0; s[i-1] != '\n'; c = c + i)
{
if (l - c <= WRAP)
for (i = c; i <= l; ++i)
putchar(s[i]);
else
{
for (i = c + WRAP - 1; i >= c && s[i] != ' ' && s[i] != '\t'; --i)
;
if (i == (c-1))
{
for (i = c + WRAP; s[i] != ' ' && s[i] != '\t' && s[i] != '\n'; ++i)
;
for (ii = c; ii < i; ++ii)
putchar(s[ii]);
putchar('\n');
if (s[i] != '\n')
++i;
}
else if (i == c)
++i;
else
{
for (ii = c; ii < i; ++ii)
putchar(s[ii]);
putchar('\n');
++i;
}
}
}
}
我写了一个名为wraptest的文件,其中包括以下内容:
asd
asdf
asd fg
asdflkjasdad sasdf
adsfa asdfasfd adfsdf
asd asdfadfasdfad
this line
运行时
./wrap < wraptest
我得到以下
asd
asdf
asd fg
asdflkjasdad
sasdf
adsfa
asdfasfd
asd
asdfadfasdfad
Segmentation fault (core dumped)
Valgrind给了我以下内容:
==6729== Conditional jump or move depends on uninitialised value(s)
==6729== at 0x80486EE: wrap (wrap.c:37)
==6729== by 0x80484CC: main (wrap.c:15)
==6729== Uninitialised value was created by a stack allocation
==6729== at 0x80484A2: main (wrap.c:10)
==6729==
==6729== Invalid read of size 1
==6729== at 0x80486E9: wrap (wrap.c:37)
==6729== by 0x80484CC: main (wrap.c:15)
==6729== Address 0xbe8a3623 is not stack'd, malloc'd or (recently) free'd
==6729==
==6729==
==6729== Process terminating with default action of signal 11 (SIGSEGV)
==6729== Access not within mapped region at address 0xBE8A3623
==6729== at 0x80486E9: wrap (wrap.c:37)
==6729== by 0x80484CC: main (wrap.c:15)
==6729== If you believe this happened as a result of a stack
==6729== overflow in your program's main thread (unlikely but
==6729== possible), you can try to increase the size of the
==6729== main thread stack using the --main-stacksize= flag.
==6729== The main thread stack size used in this run was 8388608.
==6729==
==6729== HEAP SUMMARY:
==6729== in use at exit: 0 bytes in 0 blocks
==6729== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==6729==
==6729== All heap blocks were freed -- no leaks are possible
==6729==
==6729== For counts of detected and suppressed errors, rerun with: -v
==6729== ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
那么错误是什么?我一直在寻找大约一个小时,但我还没有找到它。
答案 0 :(得分:1)
您永远不会检查i
的值,但它会在wrap
函数中索引您的字符串数组。这是i
值在崩溃之前在我的机器上增长到1000的位置。我建议将它放在调试器上,简化代码,或者至少检查索引到字符串缓冲区的变量,以确保它不会超过缓冲区的末尾。 HTH!
修改强>
既然你问过,我会在Ubuntu 12.04 LTS上向你展示我是如何调试它的。
从shell中调用名为sotest.c
# use the -g for debug info
gcc -g sotest.c -o sotest
# invoke the gnu debugger
gdb sotest
你会看到:
GNU gdb(Ubuntu / Linaro 7.4-2012.04-0ubuntu2.1)7.4-2012.04版权所有 (C)2012 Free Software Foundation,Inc。许可证GPLv3 +:GNU GPL 版本3或更高版本http://gnu.org/licenses/gpl.html这是免费的 软件:您可以自由更改并重新分发它。没有 保证,在法律允许的范围内。输入“显示复制”和 详情请参阅“保修”。此GDB配置为 “i686的Linux的GNU的”。有关错误报告说明,请参阅: http://bugs.launchpad.net/gdb-linaro/ ...从中读取符号 /home/macduff/sotest...done。 (GDB)
然后,使用输入文件调用程序:
run < wraptest
然后你会得到一些带有堆栈跟踪的输出文本
编程接收信号SIGSEGV,分段故障。 0x08048666 in 包裹( s = 0xbfffebd4“asd \ n \ 030 \ 313 \ 375 \ 267 \ 254 | \ 376 \ 267 \ f \ 356 \ 377 \ 277”,l = 3) 在sotest.c:58 58 for(i = c + WRAP - 1; i&gt; = c&amp;&amp; s [i]!=''&amp;&amp; s [i]!='\ t'; - -i)