함수를 사용하는 간단한 시계 프로그램이 있습니다 math.h
. 현재 사용하고 있는 GCC 버전 Kubuntu 21.10
은 이고 (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
? 어떻게 수정할 수 있나요?
답변1
필요한 정보는 math.h 헤더 파일이 아니라 C 표준 라이브러리의 소스 코드에 있습니다. 불행하게도 다음과 같이서비스 디버그 정보문서에 따르면 Ubuntu Debuginfod 서비스는 현재 사용할 수 없습니다.
현재 서비스는 DWARF 정보만 제공합니다. 향후 인덱싱 및 소스코드 서비스도 제공할 예정이다.
dir
그러나 소스 코드를 로컬 디렉터리에 다운로드하고 -d
명령(또는 그에 상응하는 명령줄)을 통해 gdb가 해당 디렉터리를 가리키도록 할 수 있습니다. 전임자. 주어진:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]) {
double x = atof(argv[1]);
double y = sin(x);
printf("sin(%.3f) = %.3f\n", x, y);
return(0);
}
그 다음에
mkdir -p src && cd src
apt-get source libc6
cd ..
gcc -g -o myprog myprog.c -lm
DEBUGINFOD_URLS="https://debuginfod.ubuntu.com" gdb -d ./src/glibc-2.35 myprog
다음 대화형 세션 결과
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
[copyright header skipped]
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from myprog...
(gdb) b 8
Breakpoint 1 at 0x11b8: file myprog.c, line 8.
(gdb) r 3.14
Starting program: /home/steeldriver/myprog 3.14
This GDB supports auto-downloading debuginfo from the following URLs:
https://debuginfod.ubuntu.com
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main (argc=2, argv=0x7fffffffdf98) at myprog.c:8
8 double y = sin(x);
(gdb) s
__sin_avx (x=3.1400000000000001) at ../sysdeps/ieee754/dbl-64/s_sin.c:201
201 {
(gdb)