分段故障(核心转储)

时间:2014-06-15 23:58:05

标签: c pointers segmentation-fault

我在c中编写了一个基本上复制文件的程序,但是我收到了这个错误:分段错误(核心转储)。根据我的阅读情况,我认为这是因为我试图访问尚未分配的内存。我是一个新手,当谈到c和我吮吸指针,所以我想知道你们是否可以告诉我哪个指针导致了这个以及如果可能的话如何解决它。顺便说一句,这个程序应该是一个守护进程,但我还没有把任何东西放在底部的无限循环中。 这是我的代码:

#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); 

} ls的结果是:

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

D1和D2是文件夹,在D1中是我要复制到D2的三个文本文档。 另一个问题是,这是延迟错误还是直接错误?因为我怀疑这个消息会出现在带有两个整数的代码行上。 先谢谢你们。

1 个答案:

答案 0 :(得分:2)

这个循环错了:

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

可能每次ent都指向同一个内存块,readdir函数会更新它。因此,当您保存该指针时,最终会得到包含无效指针的列表(可能最终都指向同一个字符串)。此外,一旦到达目录末尾,就可以取消分配字符串。

如果要在关闭目录后或在再次调用readdir后使用readdir的结果,则需要获取数据的副本。在这种情况下,您可以使用strdup,在操作结束时释放字符串通常是一种好方法。

这可能是也可能不是您的段错误的原因。另一件需要检查的事情是,如果sizeSourcesizeDest点击30,您应该突破循环。

strcmp循环中,您应该在dif = 0循环的开头设置i,而不是在else块中设置。{/ p>


更新:(OP显示更多代码)

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

您正在复制到一个狂野指针,这可能是段错误的原因。 strcpy没有分配任何内存,它预计你已经分配了足够的内存。

一种可能的解决方法是:

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

或者(不使用VLA):

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

对pathDest做同样的事情。

NB。考虑将closedir行移到readdir循环之后;一般来说,您应该尽可能接近开始和关闭资源,分别开始和结束使用它们;这使您的代码更易于维护。

相关问题