简体   繁体   English

分段故障(核心已转储)

[英]Segmentation fault (core dumped)

I'm writing a program in c that basically copies files, but I'm getting this error: Segmentation fault (core dumped). 我正在用c编写一个基本上复制文件的程序,但出现此错误:分段错误(核心已转储)。 From what I'm reading I think it's because I'm trying to access memory that hasn't been allocated yet. 从我阅读的内容来看,我认为这是因为我正在尝试访问尚未分配的内存。 I'm a newbie when it comes to c and I suck at pointers, so I was wondering if you guys could tell me which pointer is causing this and how to fix it if possible. 我是c的新手,我很喜欢指针,所以我想知道你们是否可以告诉我是哪个指针导致了这个问题,以及如何解决它。 Btw, this program is supposed to be a daemon, but I haven't put anything inside the infinite while loop at the bottom. 顺便说一句,该程序应该是守护程序,但是我没有在底部的while循环内放入任何内容。 Here is my code: 这是我的代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <dirent.h>

int main(int c, char *argv[]) {
char *source, *destination;
char *list1[30], *list2[30], *listDif[30];
unsigned char buffer[4096];
int i=0, x=0, sizeSource=0, sizeDest=0, sizeDif=0;
int outft, inft,fileread;
int sleeper;
struct dirent *ent, *ent1;

//Check number of arguments
if(c<3) 
{
    printf("Daemon wrongly called\n");
    printf("How to use: <daemon name> <orginDirectory> <destinationDirectory> \n");
    printf("or : <daemon name> <orginDirectory> <destinationDirectory> <sleeperTime(seconds)>");
    return 0;
}

//Checks if sleeper time is given or will be the default 5minutes
/*if(c=4)
{
    char *p;
    errno = 0;
    long conv = strtol(argv[3], &p, 10);
    if(errno != 0 || *p != '\0') 
    {
        printf("Number given for sleeper incorrect, it has to be an integer value.\n");
        return(0);
    } else 
    {
    sleeper = conv;
    }
} else
{
    sleeper = 300;
}*/

//Get path of directories from arguments
source = argv[1];
destination = argv[2];

//Check if directories exist
DIR* dirSource = opendir(source);
if (!dirSource)
{
    printf("Source directory incorrect\n");
    return 0;
}
DIR* dirDest = opendir(destination);
if (!dirDest)
{
    printf("Destination directory incorrect\n");
    return 0;
}

/* save all the files and directories within directory */
while ((ent = readdir (dirSource)) != NULL) {
    list1[sizeSource] = strdup(ent->d_name);    
    sizeSource++;
    if(sizeSource>=30){break;}
}
closedir(dirSource);
while((ent1 = readdir (dirDest)) != NULL) {
    list2[sizeDest] = strdup(ent1->d_name);
    sizeDest++;
    if(sizeDest>=30){break;}
}
closedir(dirDest);
/* Verify the diferences between the directories and save them */
int z;
int dif = 0; //0 - False | 1 - True
printf("Diferenças:\n");
for(i=0;i<sizeSource;i++){
    dif = 0;
    for(z=0;z<sizeDest;z++){
        if(strcmp(list1[i],list2[z])==0){ //If there is no match, it saves the name of the file to listDif[]
            dif = 1; 
            break;
        }   
    }
    if(dif==0) {
        printf("%s\n",list1[i]);
        listDif[sizeDif] = list1[i];
        sizeDif++;
    }
}

/* This code will copy the files */
z=0;
while(z!=sizeDif){
    // output file opened or created
    char *pathSource, *pathDest;        

    strcpy(pathSource, source);
    strcat(pathSource, "/");
    strcat(pathSource, listDif[z]);

    strcpy(pathDest, destination);
    strcat(pathDest, "/");
    strcat(pathDest, listDif[z]);

    // output file opened or created
    if((outft = open(pathDest, O_CREAT | O_APPEND | O_RDWR))==-1){
        perror("open");
    }
    // lets open the input file
    inft = open(pathSource, O_RDONLY);
    if(inft >0){ // there are things to read from the input
        fileread = read(inft, buffer, sizeof(buffer));
        printf("%s\n", buffer);
        write(outft, buffer, fileread);
        close(inft);
    }
    close(outft);
}



/* Our process ID and Session ID */
pid_t pid, sid;

/* Fork off the parent process */
pid = fork();
if (pid < 0) {
        exit(EXIT_FAILURE);
}
/* If we got a good PID, then
   we can exit the parent process. */
if (pid > 0) {
        exit(EXIT_SUCCESS);
}

/* Change the file mode mask */
umask(0);

/* Open any logs here */        

/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
        /* Log the failure */
        exit(EXIT_FAILURE);
}



/* Change the current working directory */
if ((chdir("/")) < 0) {
        /* Log the failure */
        exit(EXIT_FAILURE);
}

/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);

/* Daemon-specific initialization goes here */

/* The Big Loop */
while (1) {

   //sleep(5); /* wait 5 seconds */
}
exit(EXIT_SUCCESS); 

} The result of ls is: ls的结果是:

ubuntu@ubuntu:~/Desktop$ ls
Concatenar_Strings.c   core  D2      daemon.c   examples.desktop
Concatenar_Strings.c~  D1    daemon  daemon.c~  ubiquity.desktop

D1 and D2 are folders, and in D1 are three text documents that I want to copy into D2. D1和D2是文件夹,在D1中是我要复制到D2中的三个文本文档。 One other question, is this a delayed error or an immediate one? 还有一个问题,这是延迟的错误还是立即的错误? Because I doubt this message would appear on a code line that with two integers. 因为我怀疑此消息会出现在带有两个整数的代码行上。 Thanks in advance guys. 在此先感谢大家。

This loop is wrong: 此循环是错误的:

while ((ent = readdir (dirSource)) != NULL) {
    list1[sizeSource] = ent->d_name;    

Probably, ent points to the same memory block every time, and the readdir function updates it. 可能每次ent指向同一个内存块,而readdir函数会对其进行更新。 So when you save that pointer, you end up with your list containing invalid pointers (probably end up all pointing to the same string). 因此,当您保存该指针时,最终将导致列表中包含无效的指针(可能最终所有指针都指向同一字符串)。 Further, the string may be deallocated once you got to the end of the directory. 此外,一旦到达目录末尾,该字符串可能会被释放。

If you want to use the result of readdir after closing the directory or after calling readdir again you will need to take a copy of the data. 如果你想使用的结果readdir关闭目录后,或打完电话后readdir再次,你将需要采取的数据的副本。 In this case you can use strdup and it is usually good style to free the string at the end of the operation. 在这种情况下,您可以使用strdup ,这通常是一种很好的样式,可以在操作结束时释放字符串。

This may or may not have been the cause of your segfault. 这可能是也可能不是您的段错误的原因。 Another thing to check is that you should break out of your loops if sizeSource or sizeDest hits 30 . 要检查的另一件事是,如果sizeSourcesizeDest达到30则应该跳出循环。

In the strcmp loop, you should really set dif = 0 at the start of the i loop, instead of in an else block. strcmp循环中,实际上应该在i循环的开始而不是在else块中设置dif = 0


Update: (more code shown by OP) 更新: (OP显示更多代码)

char *pathSource, *pathDest;
strcpy(pathSource, source);

You are copying to a wild pointer, which is a likely cause of segfaults. 您正在复制到野生指针,这很可能导致段错误。 strcpy does not allocate any memory, it expects that you have already allocated enough. strcpy不分配任何内存,它期望您已经分配了足够的内存。

One possible fix would be: 一种可能的解决办法是:

char pathSource[strlen(source) + 1 + strlen(listDif[z]) + 1];
sprintf(pathSource, "%s/%s", source, listDif[z]);

Alternatively (without using VLA): 或者(不使用VLA):

char pathSource[MAX_PATH];   // where MAX_PATH is some large number
snprintf(pathSource, MAX_PATH, "%s/%s", source, listDif[z]);

Do the same thing for pathDest. 对pathDest执行相同的操作。

NB. NB。 Consider moving the closedir lines up to after the readdir loops; 考虑在readdir循环之后将closedir行向上移动; generally speaking you should open and close a resource as close as possible to the times you start and finish using them respectively; 一般来说,您应该在开始和结束使用它们的时间尽可能接近的时候打开和关闭资源; this makes your code easier to maintain. 这使您的代码更易于维护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM