Eu tenho um programa de relógio simples que usa math.h
funções. Estou atualmente em Kubuntu 21.10
, a versão GCC é (Ubuntu 12.2.0-3ubuntu1) 12.2.0
, e a versão GDB é (Ubuntu 12.1-3ubuntu2) 12.1
.
O código-fonte do programa (embora possa não ser necessário):
#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;
}
Quando compilo o programa com gcc clock.c -lm -g
, e o executo com gdb ./a.out
, permito gdb
o download de informações de depuração de https://debuginfod.ubuntu.com
. Eu defino o ponto de interrupção em line 175
(que usa sin
a função), então entro step
e vejo este erro:
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.
A meu ver, ele falha ao baixar as informações de depuração para sin
a função aqui. Eu tentei pesquisar na internet para perguntas semelhantes, mas não consegui encontrar nada semelhante.
Qual é o problema aqui com o meu gdb
e como posso corrigi-lo?
A informação que você precisa não está no arquivo de cabeçalho math.h, está no código-fonte da biblioteca C padrão. Infelizmente, conforme observado na documentação Service - Debuginfod , o serviço Ubuntu Debuginfod atualmente não fornece isso:
No entanto, você pode baixar o código-fonte para um diretório local e apontar o gdb para ele por meio do
dir
comando (ou seu-d
equivalente na linha de comando). Ex. dado:então
resultados na seguinte sessão interativa