c - 如何解决C中的SIGSEGV、段错误?

标签 c unix

我正在开发一个程序,用于从文本文件中读取数据并使用霍夫曼编码对其进行编码。我已经运行了 2-3 次,除了一条错误消息之外什么也没有显示:

Program received signal SIGSEGV, Segmentation fault.
__strcpy_sse2 () at ../sysdeps/x86_64/multiarch/../strcpy.S:57
57    ../sysdeps/x86_64/multiarch/../strcpy.S: No such file or directory.

当我调试程序时,我将问题追溯到以下函数:

// walk the tree and put 0s and 1s
void build_bcode_from_tree(node n, char *s, int len)
{
    static char *out = buf;
    if (n->c) {
        s[len] = 0;
        strcpy(out, s);
        code[n->c] = out;
        out += len + 1;
        return;
    }

    s[len] = '0'; build_bcode_from_tree(n->left,  s, len + 1);
    s[len] = '1'; build_bcode_from_tree(n->right, s, len + 1);
}

我做错了什么?

完整代码如下:

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

typedef struct node_t {
    struct node_t *left, *right;
    int freq;
    char c;
} *node;

struct node_t pool[256] = {{0}};
node qqq[255], *q = qqq - 1;
int n_nodes = 0, qend = 1;
char *code[128] = {0}, buf[1024];

//creating tree
node create_tree(int freq, char c, node a, node b)
{
    node n = pool + n_nodes++;
    if (freq) n->c = c, n->freq = freq;
    else {
        n->left = a, n->right = b;
        n->freq = a->freq + b->freq;
    }
    return n;
}

// priority queue according to frequency
void qinsert(node n)
{
    int j, i = qend++;
    while ((j = i / 2)) {
        if (q[j]->freq <= n->freq) break;
        q[i] = q[j], i = j;
    }
    q[i] = n;
}

node qremove()
{
    int i, l;
    node n = q[i = 1];

    if (qend < 2) return 0;
    qend--;
    while ((l = i * 2) < qend) {
        if (l + 1 < qend && q[l + 1]->freq < q[l]->freq) l++;
        q[i] = q[l], i = l;
    }
    q[i] = q[qend];
    return n;
}

// walk the tree and put 0s and 1s
void build_bcode_from_tree(node n, char *s, int len)
{
    static char *out = buf;
    if (n->c) {
        s[len] = 0;
        strcpy(out, s);
        code[n->c] = out;
        out += len + 1;
        return;
    }

    s[len] = '0'; build_bcode_from_tree(n->left,  s, len + 1);
    s[len] = '1'; build_bcode_from_tree(n->right, s, len + 1);
}

// individual binary representation
void ind_repre(const char *s)
{
    int i, freq[128] = {0};
    char c[16];

    while (*s) freq[(int)*s++]++;

    for (i = 0; i < 128; i++)
        if (freq[i]) qinsert(create_tree(freq[i], i, 0, 0));

    while (qend > 2)
        qinsert(create_tree(0, 0, qremove(), qremove()));

    build_bcode_from_tree(q[1], c, 0);
}

// endode the whole file data
void compress(const char *s, char *out)
{
    while (*s) {
        strcpy(out, code[*s]);
        out += strlen(code[*s++]);
    }
}

//showing decode data
void decompress(const char *s, node t)
{
    FILE *filew;
    filew = fopen("output.txt", "w");
    node n = t;
    while (*s) {
        if (*s++ == '0') n = n->left;
        else n = n->right;
        // if (n->c) putchar(n->c), n = t;
        if (n->c) fprintf(filew,"%c", n->c), n = t;
    }
    putchar('\n');
    if (t != n) printf("wrong input\n");
  fclose(filew);

}

// main function
int main(void)
{
    int i;
    const char *str;
  char buff[1024];
    // read from file
    char txt[1024];
    FILE *file;
    size_t nread;

    file = fopen("index.html", "r");
    if (file == NULL) {
            printf("There is no file with this name!!\n");
            exit(-1);
    } else {

            while ((nread = fread(txt, 1, sizeof txt, file)) > 0)
                    fwrite(txt, 1, nread, stdout);
            if (ferror(file)) {

            }
            fclose(file);
    }

 str = txt;
    ind_repre(str);
    for (i = 0; i < 128; i++)
        if (code[i]) printf("'%c': %s\n", i, code[i]);

    compress(str, buff);
    printf("compressedData: %s\n", buff);

    decompress(buff, q[1]);
    printf("decoding done ! check output file\n");

    return 0;
}

最佳答案

调试器消息显示,确实调用了 strcpy()罪魁祸首是:

__strcpy_sse2 () at ../sysdeps/x86_64/multiarch/../strcpy.S:57

从您分享的代码来看,缓冲区buf到其中out点似乎不够大,无法容纳长度为 len 的字符串,您尝试将其复制到其中。或者,也有可能 buf不在进程内存的可写部分。

无论如何,请确保 out指向一个可写缓冲区,该缓冲区足够大,也许可以通过为其分配一些空间,例如:

static char *out = NULL;

if (out == NULL)
    out = malloc(len);

这应该可以解决您的问题。

关于c - 如何解决C中的SIGSEGV、段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47315266/

相关文章:

c - GDB 影响 setcontext 结果

您能解释一下 efilib.h 中的这个 C 定义吗?

c - 在二维数组中搜索元素,C 编程

unix - 为什么 unix 进程的内核堆栈位于上下文的动态部分

java - Git:重构文件名后无法清理工作副本

c - 如何使用写函数格式化字符串?

c - 阶乘与递归

c++ - C++ 中的 Random() 效率

bash - 如何在ssh脚本中获取嵌套的sftp以等待密码提示

linux - 以父脚本的用户身份运行 shell 下标