我有一个使用math.h
函数的简单时钟程序。我目前在Kubuntu 21.10
,GCC版本是(Ubuntu 12.2.0-3ubuntu1) 12.2.0
,GDB版本是(Ubuntu 12.1-3ubuntu2) 12.1
。
程序源代码(虽然可能不需要):
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include "conio.h"
#include <sys/ioctl.h>
#include <stdlib.h>
#define PI 3.14159265358979323846264338327950288419716939937510
#define RAD_90 1.570796 // precomputed value of 90 degrees in radians
#define RAD_30 0.523599 // precomputed value of 30 degrees in radians
#define RAD_6 0.104720 // precomputed value of 6 degree in radians
#define RAD_1 0.017453 // precomputed value of 1 degree in radians
#define X 0 // x co-ordinate in array
#define Y 1 // y co-ordinate in array
int COLUMNS, ROWS;
#define CLOCK_RADIUS (COLUMNS/2)-1
#define FPS 24
#define MOVE_TO_HOME() (printf("\033[H"))
#define CLEAR_TERMINAL_SCREEN() (printf("\033[2J"))
#define cls() (CLEAR_TERMINAL_SCREEN())
void die(const char *s) {
cls();
printf("clock: error: %s: ", s);
fflush(stdout);
perror(NULL);
fflush(stderr);
exit(1);
}
char **output/*[ROWS][COLUMNS*2]*/;
struct tm *t = NULL;
void get_window_size(int *rows, int *cols) {;
struct winsize ws;
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
if(write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) die("write");
fflush(stdout);
char buf[32];
unsigned int i = 0;
if(write(STDOUT_FILENO, "\x1b[6n", 4) != 4) die("write");
printf("\r\n");
fflush(stdout);
while(i < (sizeof(buf)-1)) {
if(read(STDIN_FILENO, &buf[i], 1) != 1) die("read");
if(buf[i] == 'R') break;
i++;
}
buf[i] = '\0';
if((buf[0] != '\x1b') || (buf[1] != '[')) die("\\x1b[6n read failure");
if(sscanf(&buf[2], "%d;%d", rows, cols) != 2) die("sscanf(146)");
cls();
} else {
*cols = ws.ws_col;
*rows = ws.ws_row;
}
}
void print_char(char c, int x, int y) {
if((x >= 0) && (y >= 0) && (x < COLUMNS) && (y < ROWS)) {
output[y][x*2] = c;
}
}
double deg_to_rad(int deg) {
return deg*PI/180;
}
void clear_buffer() {
for(int i = 0;i < ROWS;i++) {
memset(output[i], ' ', COLUMNS*2);
}
output[ROWS-1][COLUMNS*2] = '\0';
}
void print_buffer() {
for(int i = 0;i < ROWS;i++) {
puts(output[i]);
}
}
void print_circle(char body, int r, int center[]) {
if(r == 0) {
print_char(body, center[X], center[Y]);
return;
}
int offset[2], prev_offset[2] = {-1, -1};
double ang = 0, ang_leap;
ang_leap = deg_to_rad((1*360)/(2*PI*r));
if(ang_leap > RAD_1) {
ang_leap = RAD_1;
} else if(ang_leap == 0) {
ang_leap = 0.0001;
}
while(ang <= RAD_90) {
offset[X] = round(sin(ang)*r);
offset[Y] = round(cos(ang)*r);
if((offset[X] == prev_offset[X]) && (offset[Y] == prev_offset[Y])) {
ang += ang_leap;
continue;
}
print_char(body, center[X]+offset[X], center[Y]+offset[Y]); // 1st quadrant
print_char(body, center[X]-offset[X], center[Y]+offset[Y]); // 2nd quadrant
print_char(body, center[X]-offset[X], center[Y]-offset[Y]); // 3rd quadrant
print_char(body, center[X]+offset[X], center[Y]-offset[Y]); // 4th quadrant
prev_offset[X] = offset[X];
prev_offset[Y] = offset[Y];
ang += ang_leap;
}
}
void print_numbers(int r, int center[]) {
/*
* deg_to_rad(360/NUM_OF_NUMBERS) = ang
* => deg_to_rad(360/12) = ang
* => ang = deg_to_rad(30)
*
*
* sin(ang) = P/H
* = sin(ang)*H = P
*
* => offset_x = sin(ang)*r
* offset_y = cos(ang)*r
*/
int offset[2];
for(int i = 1;i <= 12;i++) {
offset[X] = round(sin(RAD_30*i)*r);
offset[Y] = round(cos(RAD_30*i)*r);
if(i >= 10) {
print_char((i/10)+'0', center[X]+offset[X], center[Y]-offset[Y]);
print_char((i%10)+'0', center[X]+offset[X]+1, center[Y]-offset[Y]);
} else {
print_char(i+'0', center[X]+offset[X], center[Y]-offset[Y]);
}
}
}
void print_hands(int r, int center[], struct tm t) {
int len, offset[2];
double ang, sin_value, cos_value;
char body;
// second hand
body = '.';
len = (r*80)/100;
ang = t.tm_sec*RAD_6;
sin_value = sin(ang);
cos_value = cos(ang);
for(int i = 0;i <= len;i++) {
offset[X] = round(sin_value*i);
offset[Y] = round(cos_value*i);
print_char(body, center[X]+offset[X], center[Y]-offset[Y]);
}
// minute hand
body = '*';
len = (r*65)/100;
ang = deg_to_rad((t.tm_min*6)/*+(t.tm_sec/10)*/); // seconds adjustement causes confusion
sin_value = sin(ang);
cos_value = cos(ang);
for(int i = 0;i <= len;i++) {
offset[X] = round(sin_value*i);
offset[Y] = round(cos_value*i);
print_char(body, center[X]+offset[X], center[Y]-offset[Y]);
}
// hour hand
body = '@';
len = (r*40)/100;
ang = deg_to_rad((t.tm_hour*30)+(t.tm_min/2)+(t.tm_sec/120));
sin_value = sin(ang);
cos_value = cos(ang);
for(int i = 0;i <= len;i++) {
offset[X] = round(sin_value*i);
offset[Y] = round(cos_value*i);
print_char(body, center[X]+offset[X], center[Y]-offset[Y]);
}
}
struct tm *get_time() {
time_t seconds = time(NULL);
if(seconds == -1) {
perror("error while calling function time()");
return NULL;
}
struct tm *tm = localtime(&seconds);
if(tm == NULL) {
perror("error while calling function localtime()");
return NULL;
}
return tm;
}
int print_clock() {
int center[] = {COLUMNS/2, ROWS/2};
print_circle('.', CLOCK_RADIUS, center);
print_numbers(CLOCK_RADIUS, center);
t = get_time();
if(t == NULL) {
return 1;
}
print_hands(CLOCK_RADIUS, center, *t);
print_char('@', center[X], center[Y]);
return 0;
}
void print_centered(int col_size, char *str) {
int str_len = strlen(str);
int start_pos = col_size-(str_len/2);
for(int i = 0;i < start_pos;i++) {
printf(" ");
}
printf("%s", str);
}
int main() {
get_window_size(&ROWS, &COLUMNS);
if(ROWS > COLUMNS/2) {
COLUMNS -= 2;
COLUMNS /= 2;
ROWS = COLUMNS;
} else if(COLUMNS/2 > ROWS) {
ROWS -= 2;
COLUMNS = ROWS;
}
output = malloc(sizeof(char*)*ROWS);
for(int i = 0;i < ROWS;i++) {
output[i] = malloc(sizeof(char)*((COLUMNS*2)+1));
}
CLEAR_TERMINAL_SCREEN();
while(!kbhit()) {
MOVE_TO_HOME();
clear_buffer();
if(print_clock()) {
return 1;
}
print_buffer();
print_centered(COLUMNS, asctime(t));
usleep((1000*1000)/FPS);
}
for(int i = 0;i < ROWS;i++) {
free(output[i]);
}
free(output);
return 0;
}
当我使用 编译程序并gcc clock.c -lm -g
使用 运行它时gdb ./a.out
,我允许gdb
从https://debuginfod.ubuntu.com
. 我在line 175
(使用sin
函数)处设置断点,然后输入step
并看到此错误:
Breakpoint 1, print_hands (r=17, center=0x7fffffffda20, t=...) at clock.c:175
175 sin_value = sin(ang);
(gdb) step
__sin_fma (x=0.83775999999999995) at ../sysdeps/ieee754/dbl-64/s_sin.c:201
Download failed: Invalid argument. Continuing without source file ./math/../sysdeps/ieee754/dbl-64/s_sin.c.
201 ../sysdeps/ieee754/dbl-64/s_sin.c: No such file or directory.
如我所见,它无法sin
在此处下载功能的调试信息。我尝试在互联网上搜索类似问题,但找不到任何类似问题。
我的问题是什么gdb
,我该如何纠正?
您需要的信息不在 math.h 头文件中,而是在 C 标准库的源代码中。不幸的是,正如Service - Debuginfod文档中所述,Ubuntu Debuginfod 服务目前不提供:
dir
但是,您可以将源代码下载到本地目录,并通过命令(或其-d
等效的命令行)将 gdb 指向该目录。前任。给出:然后
导致以下交互式会话