Windows

时间:2018-03-21 01:09:09

标签: c linux windows ubuntu gdb

我的任务是在以下代码中找到错误并修复它:

/* $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”)相关,但找不到任何可以帮助我的东西。

这是我的makefile:

all: 
    gcc -g -Wall -o count-words count-words.c 

clean: 
    rm -f count-words 

提前致谢

2 个答案:

答案 0 :(得分:1)

  

我问为什么gdb没有发生

在真实(或虚拟)UNIX系统上运行时, 与GDB一起发生。

在Windows下的#Ubuntu&#34; Ubuntu下运行时并没有发生这种情况。环境,因为那个环境正在疯狂sh * t。特别是,出于某种原因,Windows子系统通常只读取具有可写权限的部分(.rodata,可能还有.text)(这就是程序不再崩溃的原因),但只有在运行时调试器下的程序。

我不知道为什么Windows会这样做。

请注意,调试器执行需要写入(只读).text部分才能插入断点。在真正的UNIX系统上,这是通过ptrace(PTRACE_POKETEXT, ...)系统调用来实现的,该系统调用会更新只读页面,但为只有(正在调试)的过程保留只读

我猜测Windows不能完全模仿这种行为(特别是在更新后不会对页面进行写保护)。

P.S。一般来说,在Windows上使用&#34; Ubuntu&#34;学习Ubuntu会充满像这样的陷阱。

,使用虚拟机可能会更好地

答案 1 :(得分:0)

此功能错误

char *words(int count) {
  char *words = "words";
  if(count==1) 
    words[strlen(words)-1] = '\0';
  return words;
}

指针words指向字符串文字"words"。修改字符串 literal是未定义的行为,并且在大多数系统字符串文字中存储 只读内存,所以这样做

    words[strlen(words)-1] = '\0';

将导致段错误。这就是你在Ubuntu中看到的行为。我不知道 字符串文字存储在Windows可执行文件中,但修改字符串 文字是未定义的行为,任何事情都可能发生,尝试是没有意义的 推断为什么有时候事情会起作用,为什么有时事情不起作用。那是 未定义行为的本质。

修改

  

巴勃罗谢谢,但我不是在问这个错误本身,以及为什么发生了分段错误。我问为什么gdb不会发生这种情况。对不起,如果那还不够清楚。

我不知道为什么它不会发生在您身上,但是当我在我的gdb上运行您的代码时,我得到:

Reading symbols from ./bug...done.
(gdb) b 8
Breakpoint 1 at 0x6fc: file bug.c, line 8.
(gdb) r hey
Starting program: /tmp/bug hey

Breakpoint 1, words (count=1) at bug.c:8
8       words[strlen(words)-1] = '\0';
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x0000555555554713 in words (count=1) at bug.c:8
8       words[strlen(words)-1] = '\0';
(gdb)