发现分段错误,但之前的消息正在优化中 [英] Segmentation fault found but message before that is being optimized out

查看:47
本文介绍了发现分段错误,但之前的消息正在优化中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 GDB 在线调试器中编写了以下代码:

I wrote the following code in GDB online debugger :

#include <stdio.h>

int main()
{
  printf("jkjkkjkj");

  int p , n;
  FILE *fp;
  printf("jkjkkjkj2");
  fp = fopen("abc.txt","r");

  while ( (n = getc(fp))!= EOF)
  {
    printf( "the chareacter here is %d \n", n);
  }

  n = fclose(fp);
  return 0;
}

在执行代码时,我在尝试从文件中获取字符的行出现分段错误.我知道由于文件不存在,分段错误错误即将到来.

While executing the code I am getting a segmentation fault at the line where I am trying to fetch the characters from the file. I know that as the file does not exist the segmentation fault error is coming.

然而,让我感兴趣的是我试图在屏幕上打印的消息的缺失.我尝试检查调试器,一旦发现:

However, what intrigues me is the absence of the messages that I am trying to print on the screen. I tried checking on debugger and once I found:

optimized out written near the line no

但是,我尝试将 getchar() 放置在这里和那里,即使分段错误仍然存​​在,消息也会打印在屏幕上.

However, I tried putting getchar() here and there, the messages got printed on the screen even if the segmentation fault persists.

怎么解释?为什么会这样?为什么我将 getchar() 放在不同的地方时会打印消息?

How to explain this? Why is this happening? Why are the messages printed when I am putting getchar() at different places?

我曾尝试在 Solaris 服务器上编写此代码并使用 GCC 进行编译.代码已编译,但即使存在目录中提供的名称的文件,我也没有收到任何输出消息.

I had tried writing this code on a Solaris server and compiling using GCC. The code got compiled but I did not get any output message even when a file with the name provided in the directory existed.

推荐答案

由于 Yunnosch 的回答,您可能忘记了检查 fopen(3) 是否失败.更好的习惯是总是检查,至少通过编码:

As answered by Yunnosch, you probably forgot to check against failure of fopen(3). A better habit is to always check that, at least by coding:

  fp = fopen("abc.txt","r"); 
  if (fp == NULL) { perror("fopen abc.txt"); exit(EXIT_FAILURE); };

并养成至少在任何地方都这样做的习惯.使用 perror(3)(或 strerror(3)errno(3)) 是一个有用的习惯,因为您想要一些与失败相关的原因(由errno 可能通过 perror).

and take the habit of doing at least that everywhere. Using perror(3) (or strerror(3) with errno(3)) is a useful habit to get, since you want some reason related to the failure (given by errno perhaps thru perror).

更一般地说,始终阅读您正在使用的函数的文档(对于标准函数,至少在某些参考 网站,并且可能在 C11 标准 n1570),并处理他们的失败(至少,通过检查失败并退出时向发送有用的消息标准错误);对于 Unix 函数,请参阅他们的 man 页面(在 Linux 上,从 介绍(2)介绍(3);对于 Solaris,从 开始介绍(2) & 介绍(3)...).在您的 Unix 终端中,也尝试 man fopen ... 对于 POSIX 标准,启动 此处.

More generally, always read the documentation of functions that you are using (for standard functions, at least on some reference website, and possibly in the C11 standard n1570), and take care of handling their failure (at the very least, by checking against failure and exiting with a useful message to stderr); for Unix functions, see their man pages (on Linux, start on intro(2) and intro(3); for Solaris, start with intro(2) & intro(3)..). In your Unix terminal, try also man fopen ... For POSIX standard, start here.

让我感兴趣的是我试图在屏幕上打印的消息的缺失.

what intrigues me is the absence of the messages that I am trying to print on the screen.

这很简单.stdout 被缓冲(另见 setvbuf(3)),并且通常是行缓冲的.所以一个不以 \n 结尾的 printf 的输出仍然在缓冲区内,而不是在屏幕上.得到的习惯是几乎总是结束你的printf(3) 使用换行符控制格式字符串,或者使用 fflush(3).

That is simple. stdout is buffered (see also setvbuf(3)), and often line-buffered. So a printf which does not end with a \n has its output still inside the buffer, and not yet on the screen. The habit to get is to almost always end your printf(3) control format string with a newline, or else to flush the buffer explicitly using fflush(3).

对于新手来说,几乎没有理由避免使用明确的 \n 结束您的 printf.所以改用

For a newbie, there are few reasons to avoid ending your printf with an explicit \n. So use instead

printf("jkjkkjkj\n");

否则,在您的程序中经常调用 fflush(NULL);.顺便说一句,由于这些缓冲原因,fflush(NULL) 应该在调用 system(3), fork(2), execve(2) 和其他重要的程序范围函数.

Otherwise, call fflush(NULL); quite often in your program. BTW, for these buffering reasons, fflush(NULL) should be done before calls to system(3), fork(2), execve(2) and other important program-wide functions.

优化写在 no 行附近

optimized out written near the line no

这可能发生在 C 标准库 本身(例如在 getc 来自某些 libc.so),通常不使用调试信息编译.在实践中,请相信您的 C 标准库:与 libc 相比,您的代码中更有可能出现错误.

That probably happens in the C standard library itself (e.g. in getc from some libc.so), which is usually not compiled with debug information. In practice, trust your C standard library: you are much more likely to have bugs in your code that in libc.

你自己的源代码应该编译gcc -Wall -Wextra -g(要求 GCC 编译器提供所有警告和调试信息在 DWARF 格式中,可由 gdb 调试器使用)并且您需要在使用gdb之前改进您的代码以完全没有警告调试器.

Your own source code should be compiled with gcc -Wall -Wextra -g (asking the GCC compiler to give all warnings and debug info in DWARF format, usable by the gdb debugger) and you need to improve your code to get no warnings at all before using the gdb debugger.

注意未定义行为,花几个小时阅读关于 UB,并害怕 UB.

这篇关于发现分段错误,但之前的消息正在优化中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆