在目录

时间:2015-11-21 14:23:05

标签: c linux gcc segmentation-fault gdb

大家好,这是我在这里的第一篇文章。

我认为我的问题很愚蠢,但我找不到任何解决办法,希望你能帮助我!

所以,我和一个朋友正在编写一个小型系统监视器(学习更好/好玩),代码有两个部分:守护进程和命令行界面(现在),当我编译CLI部分时一切都很好,守护进程是特别的,因为当我编译并在编译目录中执行它时,它可以正常工作!奇怪的是,当我离开编译目录时,它给我一个分段错误!

编译器:GCC

以下是存储库:https://github.com/StefanoBelli/JASM

生成文件:

 #!/usr/bin/make -f

SHELL=/bin/sh

####    CONFIGURATION    ####

CC=gcc
DEBUG=-g
CFLAGS=-O2 -pipe -Wall -std=c11 $(DEBUG)
LIBS=
BINOUT=jasm

####    SOURCES & RULES    ####

OBJS:=$(patsubst %.c,%.o,$(wildcard *.c))

install:$(OBJS)
    $(CC) $(CFLAGS) $(LIBS) -o $(BINOUT) $(OBJS) 

clean:
    rm -fv *.o

.PHONY: install,clean

GDB输出:

(gdb) run
Starting program: /home/stefanozzz123/Devel/C.Cpp/JASM/bin/jasm 

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7a7db04 in vfprintf () from /usr/lib/libc.so.6
(gdb) 

谢谢大家们! :)

编辑:正如您在此处所要求的那样是代码:

jasm.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "queue.h"
#include "miscellaneous.h"
#include "ipc.h"




int main(int argc, char *argv[])
{
  start_daemon();
  start_server();



}

ipc.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "ipc.h"
#include "miscellaneous.h"
#include "getter.h"


static void excecute_command(int fd, char *command)
{
  /*
   *  if get* -> modulo get
   *  if start* -> modulo dei moduli
   */

   // ************************** getter ***************************************
   if(strncmp("get", command, 3)==0) {  //ricevuto comando getter
     int i;
     //char buf[BUFSIZ];

     strcpy(command, &command[3]);

     for(i=0; i<NGETTER; i++) {
       if(strcmp(getterName[i], command)==0) { //se esiste getter
         log_string("getter found :)");
         getterFunction[i](fd);
         return;
       }
     }

     log_error("getter NOT found :(");
     write(fd, "null\0", 4);
     return;
   }

   // ************************** starter **************************************
   if(strncmp("start", command, 5)==0) {  //ricevuto start modulo



     log_error("starter NOT found :(");
     write(fd, "null\0", 4);
     return;
   }


   // ************************** miscellaneous ********************************
   if(strcmp("halt", command)==0) { //spegne jasm
        log_string("# halt and catch fire, done");
        write(fd, "halt\0", 4);
        exit(0);
   }



  /*if(strcmp("getVersion", command)==0) {
    write(fd, (void *)VERSION, sizeof(VERSION));
    log_string("server reply <version> with success");
    return;
  }*/
    log_error("request not found");
    write(fd, "null\0", 4);

}

void start_server()
{
int server_sockfd, client_sockfd;
int server_len;
socklen_t client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int result;
fd_set readfds, testfds;

  server_sockfd=socket(AF_INET, SOCK_STREAM, 0);
  server_address.sin_family=AF_INET;
  server_address.sin_addr.s_addr=htonl(INADDR_ANY);
  server_address.sin_port=htons(SERVER_PORT);
  server_len=sizeof(server_address);

  bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

  listen(server_sockfd, 5);

  FD_ZERO(&readfds);
  FD_SET(server_sockfd, &readfds);

  log_string("server started");

  while(1) {
    char buf[BUFSIZ];
    char received[BUFSIZ];
    int fd;
    int nread;

    testfds=readfds;

    result=select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);

    if(result<1) {
      log_error("server fail");
      exit(1);
    }

    for(fd=0; fd<FD_SETSIZE; fd++) {
      if(FD_ISSET(fd, &testfds)) {
        if(fd==server_sockfd) {
          client_len=sizeof(client_address);
          client_sockfd=accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
          FD_SET(client_sockfd, &readfds);
          sprintf(buf, "adding client on fd %d", client_sockfd);
          log_string(buf);
        } else {
          ioctl(fd, FIONREAD, &nread);

          if(nread==0) {
            close(fd);
            FD_CLR(fd, &readfds);
            sprintf(buf, "removing client on fd %d", fd);
            log_string(buf);
          } else {
            read(fd, &received, BUFSIZ);
            sprintf(buf, "received from fd %d command <%s>", fd, received);
            log_string(buf);
            excecute_command(fd, received);
          }
        }
      }
    }
  }
}

miscellanous.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "miscellaneous.h"

char * getTime()
{
  time_t curtime;
  struct tm *loctime;
  static char *ret;

  curtime=time(NULL);
  loctime=localtime(&curtime);
  ret=asctime(loctime);
  ret[24]='\0';

  return ret;
}

void log_string(const char *message)
{
  FILE *fp;

  fp=fopen(LOGPATH, "a+");
  fprintf(fp, "[%s] %s\n", getTime(), message);
  fclose(fp);
}

void log_error(const char *message)
{
  FILE *fp;

  fp=fopen(LOGPATH, "a+");
  fprintf(fp, "[%s] ERROR: %s!\n", getTime(), message);
  fclose(fp);
}

void start_daemon()
{
  pid_t pid;
  char buf[BUFSIZ];

  log_string("boot");

  pid=fork();
  switch(pid) {
    case -1:
      log_error("fork fail");
      exit(1);
      break;

    case 0:
      log_string("fork success");
      break;

    default:
      exit(0);
      break;
  }

  if(setsid()<0) {
    log_error("setsid fail");
    exit(1);
  } else {
    log_string("setsid success");
  }

  //chiude i file descriptor di stdin, stdout, stderr
  close(0);
  close(1);
  close(2);

  sprintf(buf, "jasm started with pid %d and ppid %d", getpid(), getppid());

  log_string(buf);
}

基本上这些都是主要的......

GDB Backtrace没有说什么,因为程序运行立即停止

1 个答案:

答案 0 :(得分:0)

由于问题被标记为,让我们看看gdb如何提供帮助。在我的例子中,我已经为libc安装了debuginfo文件,因此我可以检查C库函数的参数,但在这种情况下你并不需要它,因为我们可以通过查看用户的源代码来找到bug。

(gdb) run
Starting program: ./jasm 

Program received signal SIGSEGV, Segmentation fault.
_IO_vfprintf_internal (s=0x0, format=0x4019b1 "[%s] %s\n", 
    ap=ap@entry=0x7fffffffbd38) at vfprintf.c:1295
1295    vfprintf.c: No such file or directory.
(gdb) bt
#0  _IO_vfprintf_internal (s=0x0, format=0x4019b1 "[%s] %s\n", 
    ap=ap@entry=0x7fffffffbd38) at vfprintf.c:1295
#1  0x00007ffff7a693f7 in __fprintf (stream=<optimized out>, 
    format=<optimized out>) at fprintf.c:32
#2  0x000000000040149d in log_string (message=0x4019cb "boot")
    at miscellaneous.c:46
#3  0x000000000040151f in start_daemon () at miscellaneous.c:64
#4  0x0000000000401400 in main (argc=1, argv=0x7fffffffdf78) at jasm.c:31

vfprintf的声明是:

int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);

即使我们没有安装vfprintf的源代码,我们也可以看到传递给它的第一个参数s是一个NULL流指针,这很可能是seg错误的原因

让我们看一下我们的源代码:第2帧,log_string

(gdb) frame 2
#2  0x000000000040149d in log_string (message=0x4019cb "boot")
    at miscellaneous.c:46
46    fprintf(fp, "[%s] %s\n", getTime(), message);
(gdb) print fp
$2 = (FILE *) 0x0

它就是。

#define LOGPATH "../../../../data/log/jasm.log"

void log_string(const char *message)
{
  FILE *fp;

  fp=fopen(LOGPATH, "a+");
  fprintf(fp, "[%s] %s\n", getTime(), message);
  fclose(fp);
}

void log_error(const char *message)
{
  FILE *fp;

  fp=fopen(LOGPATH, "a+");
  fprintf(fp, "[%s] ERROR: %s!\n", getTime(), message);
  fclose(fp);
}

检查fopen的返回值。它可能为NULL,具体取决于运行程序的目录。最好使用绝对路径名,可以在Makefile中设置可移植性。

write(fd, "halt\0", 4);

所有这些都应该有5个,包括尾随的NUL。 (并且绝对不必在字符串文字中明确包含\0,因为C字符串文字最后隐含地有\0。)