【发布时间】:2018-03-21 01:09:09
【问题描述】:
我的任务是找出以下代码中的错误并修复它:
/* $Id: count-words.c 858 2010-02-21 10:26:22Z tolpin $ */
#include <stdio.h>
#include <string.h>
/* return string "word" if the count is 1 or "words" otherwise */
char *words(int count) {
char *words = "words";
if(count==1)
words[strlen(words)-1] = '\0';
return words;
}
/* print a message reportint the number of words */
int print_word_count(char **argv) {
int count = 0;
char **a = argv;
while(*(a++))
++count;
printf("The sentence contains %d %s.\n", count, words(count));
return count;
}
/* print the number of words in the command line and return the number as the exit code */
int main(int argc, char **argv) {
return print_word_count(argv+1);
}
该程序适用于给它的每个单词数量,除了一个单词。使用./count-words hey 运行它会导致分段错误。
我正在使用官方 Ubuntu 应用程序在 Windows 10 上的 Linux 子系统上运行我的代码(我理解它至少是这么称呼的......)。
从终端运行程序时,我确实遇到了分段错误,但使用 gdb,由于某种原因程序运行正常:
(gdb) r hey
Starting program: .../Task 0/count-words hey
The sentence contains 1 word.
[Inferior 1 (process 87) exited with code 01]
(gdb)
在第 9 行添加断点并单步执行代码后,我得到了:
(gdb) b 9
Breakpoint 1 at 0x400579: file count-words.c, line 9.
(gdb) r hey
Starting program: /mnt/c/Users/tfrei/Google Drive/BGU/Semester F/Computer Architecture/Labs/Lab 2/Task 0/count-words hey
Breakpoint 1, words (count=1) at count-words.c:9
9 if(count==1)
(gdb) s
10 words[strlen(words)-1] = '\0';
(gdb) s
strlen () at ../sysdeps/x86_64/strlen.S:66
66 ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) s
67 in ../sysdeps/x86_64/strlen.S
(gdb) s
68 in ../sysdeps/x86_64/strlen.S
(gdb)
奇怪的是,当我从“真正的”Ubuntu(使用 Windows 10 上的虚拟机)运行相同的东西时,gdb 上确实发生了分段错误。
我倾向于认为这与我的运行时环境(“Windows 上的 Ubuntu”)有关,但找不到任何可以帮助我的东西。
这是我的生成文件:
all:
gcc -g -Wall -o count-words count-words.c
clean:
rm -f count-words
提前致谢
【问题讨论】:
-
char *words = "words";是指向字符串文字的指针,修改它是未定义的行为,并且在大多数情况下会导致段错误,因为它是只读内存。你不能修改它。 -
不要写这样的代码。
-
@Michi 我觉得奇怪的是 OP 的 gdb 没有显示段错误。
-
那是 UB。不要要求解释为什么错误的代码有时会起作用。
-
有更好的复数方式,例如
char *plural[] = { "", "s" }; printf("%d word%s", count, plural[count != 1]);
标签: c linux windows ubuntu gdb