C语言十六进制查看器代码编译失败,请求技术协助
编译Curses十六进制查看器时出现未定义引用错误
我正在完成作业任务,需要编写具备行显示、编辑、字符映射功能的十六进制查看器并扩展更多特性。老师提供了一段带西班牙语注释的示例代码,但编译失败,错误提示大量Curses相关函数未定义。
老师提供的示例代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <ctype.h> #include <string.h> #include <curses.h> #include <sys/stat.h> #include <sys/mman.h> /* Variable global para mejor legibilidad */ int fd; // Archivo a leer char *hazLinea(char *base, int dir) { char linea[100]; // La linea es mas pequeña int o=0; // Muestra 16 caracteres por cada linea o += sprintf(linea,"%08x ",dir); // offset en hexadecimal for(int i=0; i < 4; i++) { unsigned char a,b,c,d; a = base[dir+4*i+0]; b = base[dir+4*i+1]; c = base[dir+4*i+2]; d = base[dir+4*i+3]; o += sprintf(&linea[o],"%02x %02x %02x %02x ", a, b, c, d); } for(int i=0; i < 16; i++) { if (isprint(base[dir+i])) { o += sprintf(&linea[o],"%c",base[dir+i]); } else { o += sprintf(&linea[o],"."); } } sprintf(&linea[o],"\n"); return(strdup(linea)); } char *mapFile(char *filePath) { /* Abre archivo */ fd = open(filePath, O_RDONLY); if (fd == -1) { perror("Error abriendo el archivo"); return(NULL); } /* Mapea archivo */ struct stat st; fstat(fd,&st); long fs = st.st_size; char *map = mmap(0, fs, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close(fd); perror("Error mapeando el archivo"); return(NULL); } return map; } int leeChar() { int chars[5]; int ch,i=0; nodelay(stdscr, TRUE); while((ch = getch()) == ERR); /* Espera activa */ ungetch(ch); while((ch = getch()) != ERR) { chars[i++]=ch; } /* convierte a numero con todo lo leido */ int res=0; for(int j=0;j<i;j++) { res <<=8; res |= chars[j]; } return res; } int edita(char *filename) { /* Limpia pantalla */ clear(); /* Lee archivo */ char *map = mapFile(filename); if (map == NULL) { exit(EXIT_FAILURE); } for(int i= 0; i<25; i++) { // Haz linea, base y offset char *l = hazLinea(map,i*16); move(i,0); addstr(l); } refresh(); int c = getch(); while (c != 26) { switch (c) { case KEY_LEFT: break; } c = getch(); } if (munmap(map, fd) == -1) { perror("Error al desmapear"); } close(fd); return 0; } int main(int argc, char const *argv[]) { initscr(); raw(); keypad(stdscr, TRUE); /* Para obtener F1,F2,.. */ noecho(); /* El archivo se da como parametro */ if (argc != 2) { printf("Se usa %s <archivo> \n", argv[0]); return(-1); } edita((char *)argv[1]); endwin(); return 0; }
尝试的编译命令
gcc -o hex hex.c gcc -o hex hex.c -lrt
编译错误信息
$ gcc -o h hex.c /usr/bin/ld: /tmp/ccrFjiTL.o: en la función `leeChar': hex.c:(.text+0x36a): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x377): referencia a `nodelay' sin definir /usr/bin/ld: hex.c:(.text+0x37f): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x387): referencia a `wgetch' sin definir /usr/bin/ld: hex.c:(.text+0x39a): referencia a `ungetch' sin definir /usr/bin/ld: hex.c:(.text+0x3b5): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x3bd): referencia a `wgetch' sin definir /usr/bin/ld: /tmp/ccrFjiTL.o: en la función `edita': hex.c:(.text+0x422): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x42a): referencia a `wclear' sin definir /usr/bin/ld: hex.c:(.text+0x475): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x487): referencia a `wmove' sin definir /usr/bin/ld: hex.c:(.text+0x48e): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x4a2): referencia a `waddnstr' sin definir /usr/bin/ld: hex.c:(.text+0x4b3): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x4bb): referencia a `wrefresh' sin definir /usr/bin/ld: hex.c:(.text+0x4c2): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x4ca): referencia a `wgetch' sin definir /usr/bin/ld: hex.c:(.text+0x4dd): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x4e5): referencia a `wgetch' sin definir /usr/bin/ld: /tmp/ccrFjiTL.o: en la función `main': hex.c:(.text+0x543): referencia a `initscr' sin definir /usr/bin/ld: hex.c:(.text+0x548): referencia a `raw' sin definir /usr/bin/ld: hex.c:(.text+0x54f): referencia a `stdscr' sin definir /usr/bin/ld: hex.c:(.text+0x55c): referencia a `keypad' sin definir /usr/bin/ld: hex.c:(.text+0x561): referencia a `noecho' sin definir /usr/bin/ld: hex.c:(.text+0x5a1): referencia a `endwin' sin definir collect2: error: ld returned 1 exit status
解决方法
1. 问题根源
错误提示的"未定义引用"全部来自ncurses库的函数(如initscr、getch、stdscr等),你之前用的-lrt是链接实时库,和ncurses无关,编译时没有正确链接ncurses库导致这些函数找不到。
2. 安装ncurses开发库
首先确保系统上安装了ncurses的开发包:
- Debian/Ubuntu 系列:
sudo apt install libncurses5-dev libncursesw5-dev - RHEL/CentOS 系列:
sudo yum install ncurses-devel - Arch Linux:
sudo pacman -S ncurses
3. 正确编译命令
编译时添加-lncurses参数链接ncurses库:
gcc -o hex hex.c -lncurses
如果需要支持宽字符,可替换为-lncursesw。
4. 修复代码中的潜在错误
代码中munmap(map, fd)存在逻辑错误:munmap的第二个参数需要是映射的内存大小,不是文件描述符fd。同时需要释放strdup分配的内存避免泄漏,修改后的edita函数:
int edita(char *filename) { clear(); char *map = mapFile(filename); if (map == NULL) { exit(EXIT_FAILURE); } // 获取文件大小 struct stat st; fstat(fd, &st); long fs = st.st_size; for(int i= 0; i<25; i++) { char *l = hazLinea(map,i*16); move(i,0); addstr(l); free(l); // 释放strdup分配的内存 } refresh(); int c = getch(); while (c != 26) { switch (c) { case KEY_LEFT: break; } c = getch(); } if (munmap(map, fs) == -1) { // 用文件大小替换fd perror("Error al desmapear"); } close(fd); return 0; }
内容的提问来源于stack exchange,提问作者Miguel Salazar
相关产品推荐
相关产品推荐

