簡體   English   中英

分段故障(核心已轉儲)

[英]Segmentation fault (core dumped)

我正在用c編寫一個基本上復制文件的程序,但出現此錯誤:分段錯誤(核心已轉儲)。 從我閱讀的內容來看,我認為這是因為我正在嘗試訪問尚未分配的內存。 我是c的新手,我很喜歡指針,所以我想知道你們是否可以告訴我是哪個指針導致了這個問題,以及如何解決它。 順便說一句,該程序應該是守護程序,但是我沒有在底部的while循環內放入任何內容。 這是我的代碼:

#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中的三個文本文檔。 還有一個問題,這是延遲的錯誤還是立即的錯誤? 因為我懷疑此消息會出現在帶有兩個整數的代碼行上。 在此先感謝大家。

此循環是錯誤的:

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

可能每次ent指向同一個內存塊,而readdir函數會對其進行更新。 因此,當您保存該指針時,最終將導致列表中包含無效的指針(可能最終所有指針都指向同一字符串)。 此外,一旦到達目錄末尾,該字符串可能會被釋放。

如果你想使用的結果readdir關閉目錄后,或打完電話后readdir再次,你將需要采取的數據的副本。 在這種情況下,您可以使用strdup ,這通常是一種很好的樣式,可以在操作結束時釋放字符串。

這可能是也可能不是您的段錯誤的原因。 要檢查的另一件事是,如果sizeSourcesizeDest達到30則應該跳出循環。

strcmp循環中,實際上應該在i循環的開始而不是在else塊中設置dif = 0


更新: (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。 考慮在readdir循環之后將closedir行向上移動; 一般來說,您應該在開始和結束使用它們的時間盡可能接近的時候打開和關閉資源; 這使您的代碼更易於維護。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM