首页 > 解决方案 > 找到导致分段错误的行,我找不到

问题描述

目前我正在编写一个 LZ77 算法。当我尝试运行我的代码时,由于某种原因,我得到了 ZSH 分段错误。我搜索了一些主题,但找不到为此修复代码的地方。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>


/*#define pencereBoyutu 60
#define bufferBoyutu 40*/

typedef enum { false, true } bool;

// ============================================================================

int ortakBul(unsigned char window[], unsigned char str[], int strLen) {
    int j, k, yer = -1;
    int pencereBoyutu = 60;
    for (int i = 0; i <= pencereBoyutu - strLen; i++) {
        yer = k = i;

        for (j = 0; j < strLen; j++) {
            if (str[j] == window[k])
                k++;
            else
                break;
        }
        if (j == strLen)
            return yer;
    }

    return -1;
}

// ============================================================================

int compress(char* inputPath) {
    FILE *fileInput;
    FILE *fileOutput;
    bool last = false;
    int girisUzunlugu = 0;
    int cikisUzunlugu = 0;
    int setSonu = 0;
    int yer = -1;
    int i, size, shift, c_in;
    size_t bytesRead = (size_t) -1;
    int arrayBoyutu = 100;

    int pencereBoyutu = 60;
    
    int bufferBoyutu = 40;

    unsigned char c;
    unsigned char array[arrayBoyutu];
    unsigned char window[pencereBoyutu];
    unsigned char buffer[bufferBoyutu];
    unsigned char bufferYukle[bufferBoyutu];
    unsigned char str[bufferBoyutu];

    // input out açmak
    char path[30] = "";
    strcat(path, inputPath);
    fileInput = fopen(path, "rb");
    fileOutput = fopen("output/output.lz77", "wb");

    // mümkün değilse error ver
    if (!fileInput) {
        
        fprintf(stderr, "fileInput acilamiyor. %s", inputPath);
        return 0;
    }

    // fileinput uzunluğunu çek
    fseek(fileInput, 0, SEEK_END);
    girisUzunlugu = ftell(fileInput);
    fseek(fileInput, 0, SEEK_SET);

    fprintf(stdout, "Giris dosyasi boyutu: %d byte", girisUzunlugu);

    // dosya boşsa hata ver
    if (girisUzunlugu == 0)
        return 3;

    // eğer dosya boyutu arrayboyutundan düşükse hata ver
    if (girisUzunlugu < arrayBoyutu)
        return 2;

    // arrayı byte olarak oku
    fread(array, 1, arrayBoyutu, fileInput);

    
    fwrite(array, 1, pencereBoyutu, fileOutput);

    // LZ77 mantığı
    while (true) {
        if ((c_in = fgetc(fileInput)) == EOF)
            last = true;
        else
            c = (unsigned char) c_in;

        
        for (int k = 0; k < pencereBoyutu; k++)
            window[k] = array[k];

        
        for (int k = pencereBoyutu, j = 0; k < arrayBoyutu; k++, j++) {
            buffer[j] = array[k];
            str[j] = array[k];
        }

        // en uzun ortak kelimeyi bulmak
        if (setSonu != 0) {
            size = bufferBoyutu - setSonu;
            if (setSonu == bufferBoyutu)
                break;
        }
        else {
            size = bufferBoyutu;
        }

        yer = -1;
        for (i = size; i > 0; i--) {
            yer = ortakBul(window, str, i);
            if (yer != -1)
                break;
        }

        // hiç ortak bulunmaması halinde
        if (yer == -1) {
            fputc(255, fileOutput);
            fputc(buffer[0], fileOutput);
            shift = 1;
        }
        // ortak bulunması halinde
        else {
            fputc(pencereBoyutu - yer, fileOutput);
            fputc(i, fileOutput);
            if (i == bufferBoyutu) {
                shift = bufferBoyutu + 1;
                if (!last)
                    fputc(c, fileOutput);
                else
                    setSonu = 1;
            }
            else {
                if (i + setSonu != bufferBoyutu)
                    fputc(buffer[i], fileOutput);
                else
                    break;
                shift = i + 1;
            }
        }

        // Shift buffer
        for (int j = 0; j < arrayBoyutu - shift; j++)
            array[j] = array[j + shift];
        if (!last)
            array[arrayBoyutu - shift] = c;

        if (shift == 1 && last)
            setSonu++;

        
        if (shift != 1) {
            // yeni bitler oku
            bytesRead = fread(bufferYukle, 1, (size_t) shift - 1, fileInput);

            // yeni bitleri arraya yükle
            for (int k = 0, l = arrayBoyutu - shift + 1; k < shift - 1; k++, l++)
                array[l] = bufferYukle[k];

            if (last) {
                setSonu += shift;
                continue;
            }

            if (bytesRead < shift - 1)
                setSonu = shift - 1 - bytesRead;
        }
    }

    // fileoutput uzunluğunu çek
    fseek(fileOutput, 0, SEEK_END);
    cikisUzunlugu = ftell(fileOutput);
    fseek(fileOutput, 0, SEEK_SET);

    fprintf(stdout, "\nCikis dosya boyutu: %d byte\n", cikisUzunlugu);

    // I/O dosyaları kapanması
    fclose(fileInput);
    fclose(fileOutput);

    return 1;
}

// ============================================================================

// Decompress
int decompress() {
    FILE *fileInput;
    FILE *fileOutput;
    int shift, denge, ortak, c_in;
    bool done = false;
    int pencereBoyutu = 60;
    int bufferBoyutu = 40;
    int arrayBoyutu = pencereBoyutu + bufferBoyutu;

    unsigned char c;
    unsigned char window[pencereBoyutu];
    unsigned char writeBuffer[pencereBoyutu];
    unsigned char readBuffer[2];

    // i/o dosyalarin acilmasi
    fileInput = fopen("output/output.lz77", "rb");
    fileOutput = fopen("output/file", "wb");

    if (!fileInput) {
        fprintf(stderr, "fileInput açılamıyor. %s", "output.lz77");
        return 0;
    }

    
    fread(window, 1, pencereBoyutu, fileInput);
    fwrite(window, 1, pencereBoyutu, fileOutput);

    // decompress mantığı
    while (true) {
        
        size_t bytesRead = fread(readBuffer, 1, 2, fileInput);

        if (bytesRead >= 2) {
            denge = (int) readBuffer[0];
            ortak = (int) readBuffer[1];

            
            if (denge == 255) {
                denge = 0;
                c = (unsigned char) ortak;
                ortak = 0;
                shift = ortak + 1;
            }
            else {
                shift = ortak + 1;
                c_in = fgetc(fileInput);
                if (c_in == EOF)
                    done = true;
                else
                    c = (unsigned char) c_in;
            }

            
            for (int i = 0, j = pencereBoyutu - denge; i < ortak; i++, j++)
                writeBuffer[i] = window[j];
            fwrite(writeBuffer, 1, (size_t) ortak, fileOutput);

            if (!done)
                fputc(c, fileOutput);

            // Shift window
            for (int i = 0; i < pencereBoyutu - shift; i++)
                window[i] = window[i + shift];

            for (int i = 0, j = pencereBoyutu - shift; i < ortak; i++, j++)
                window[j] = writeBuffer[i];
            window[pencereBoyutu - 1] = c;
        }
        else {
            break;
        }
    }

    // dosyaları kapat
    fclose(fileInput);
    fclose(fileOutput);

    return 1;
}

// ============================================================================


int main(int argc, char* argv[]) {
    clock_t begin = clock();
    if (argc < 2) {
        printf("2 argüman gerekiyor: [-c|-d] [dosya_yolu]");
    } else {
        // decompress
        if (strcmp(argv[1], "-d") == 0) {
            int result = decompress();
            if (result == 0) {
                fprintf(stderr, "\nSikistirma islemi HATALI");
            } else if (result == 1) {
                printf("\nSikistirma islemi OK");
            }
        }
        // compress
        else if (strcmp(argv[1], "-c") == 0) {
            int result = compress(argv[2]);
            if (result == 0) {
                fprintf(stderr, "\nSikistirma islemi HATALI\n");
            } else if (result == 1) {
                printf("\nSikistirma islemi OK");
            } else if (result == 2) {
                fprintf(stderr, "\nDosya cok kucuk.\n");
            } else if (result == 3) {
                fprintf(stderr, "\nDosya bos.\n");
            }
        } else {
            printf("Gecersiz argumanlar.");
        }
    }

    // calistirma zamanını bastırmak
    clock_t end = clock();
    printf("\n\nCalistirma zamani: ");
    printf("%f", ((double) (end - begin) / CLOCKS_PER_SEC));
    printf(" [saniye]");

    return 0;
}

// ============================================================================

编译后,您必须给出运行参数:

./lz77 -c 输入.txt

当我尝试使用上面包含 100 个字符的输入运行我的应用程序时,它给了我分段错误。经过一番研究,我找不到任何理由。如果有人可以提供帮助,我会很高兴。

标签: cgcc

解决方案


推荐阅读