簡體   English   中英

從不確定長度的文件中讀取,存儲在數組中,分段錯誤

[英]Reading from file of undefined length, storing in array, segmentation fault

我想打開一個文件,讀取其內容,然后使用C代碼將其存儲在數組中。

我在Windows筆記本電腦上做到了,它可以工作,但是當我在Raspberrypi上嘗試代碼時,出現了分段錯誤。 我已經嘗試了一段時間調試我對C還是很陌生,所以我很難找到我做錯了什么。

    char *readFile(char *fileName)
    {
        FILE *ptr_file;
        char *ptr_data;
        int n = 0;
        char c;

        ptr_file = fopen(fileName, "r");
        if(ptr_file == NULL)
        {
            perror("File could not be opened.\n");
            exit(EXIT_FAILURE);
        }
        fseek(ptr_file, 0, SEEK_END);
        long f_size = ftell(ptr_file);
        fseek(ptr_file,0, SEEK_SET);
        ptr_data = (char *)malloc(f_size+1);

if(ptr_data == NULL)
{
perror("MALLOC FAILED");
exit(EXIT_FAILURE);
}

        while((c = fgetc(ptr_file)) != EOF)
        {
                ptr_data[n++] = (char)c;

        }
        ptr_data[n] = '\0';
        fclose(ptr_file);
        return ptr_data;
    }

在我看來,分段錯誤似乎在調用malloc之后的while循環中出現。

為什么它在我的筆記本電腦上而不在raspberrypi上可以工作?

同時我不明白為什么如果我這樣做我為什么在我的RPi上出現分段錯誤:

   int main(int argc, char *argv[])
            {
    char data[100] = {};
                FILE *ptr_file;
                char *ptr_data=data;
                int n = 0, i = 0;
                char c;

                ptr_file = fopen(fileName, "r");
                if(ptr_file == NULL)
                {
                    perror("File could not be opened.\n");
                    exit(EXIT_FAILURE);
                }

                while((c = fgetc(ptr_file)) != EOF)
                {
                        ptr_data[n++] = (char)c;

                }
                ptr_data[n] = '\0';
                while(i <n,i++)
    {
    printf("%c\n",data[i]);
    fclose(ptr_file);

        }

返回0; }

在不同環境下讀取文本文件時會出現一些問題。 例如,編寫新行時,在Windows上可能會消耗2個字節,而在Linux上可能僅消耗1個字節。 從文章:

C標准[ISO / IEC 9899:2011]的7.21.9.4節在以文本模式打開文本文件時為ftell()指定了以下行為: For a text stream, its file position indicator contains unspecified information, usable by the fseek function for returning the file position indicator for the stream to its position at the time of the ftell call. 因此,在文本模式下打開的流的ftell()返回值除用於fseek()調用外,絕不能用於偏移量計算。

換句話說,fseek和ftell函數的行為可能會有所不同,具體取決於您所使用的環境。
有關更多說明,您可以閱讀以下主題: https : //www.securecoding.cert.org/confluence/display/seccode/FIO14-C.+理解+ the + difference + between + text + mode + and + binary + mode +與+文件+流

也許您應該禁用Linux內存過量使用 看到這個

順便說一句,您可以考慮使用open(2)打開文件,使用fstat(2)獲取有關它的統計信息,尤其是文件大小,然后使用mmap(2)通過增大地址空間將文件投影到虛擬內存中

int fd = open(fileName, O_RDONLY);
if (fd<0) { perror(fileName); exit(EXIT_FAILURE); };
struct stat fs;
memset (&fs, 0, sizeof(fs));
if (fstat(fd, &fs)) { perror("fstat"); exit(EXIT_FAILURE); };
long pgsz = sysconf(_SC_PAGE_SIZE); // a power of two
size_t roundedsz = (fs.st_size | (pgsz-1)) + 1; // round up the size
void* ad = mmap(NULL, roundedsz, PROT_READ, MAP_SHARED, fd, (off_t)0);
if (ad == MMAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); };

然后使用ad而不是ptr_data (將變得無用)。 完成操作后,別忘了打電話給munmapclose ...

如果需要,可以在mmap之后close

閱讀高級Linux編程

暫無
暫無

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

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