【问题标题】:Getting a seg-fault when setting value of pointer设置指针值时出现段错误
【发布时间】:2016-02-22 06:26:36
【问题描述】:

这里我真的无话可说。 这是我的词法分析器文件:

#include <ctype.h>
#include <stdio.h>
#include "vector.h"

enum TokenType
{
    tok_let = -1,
    tok_iden = -2,
    tok_int = -3,
    tok_end = -4
};

typedef struct
{
    int type;
    char* str_d;
    int int_d;
} Token;

char* seed;

int i=0;

char next_char()
{
    i++;
    return seed[i-1];
}

vector* get_tokens(char* in)
{
    vector *toks;
    vector_new(toks);

    seed = in;
    char tap;
    if(isalpha(tap = next_char()))
    {
        char* iden_str="";
        iden_str += tap;
        char nc;
        while(isalnum((nc = next_char())))
            iden_str += nc; 
        if(iden_str == "let")
        {
            Token* tp;
            tp->type = tok_let;
            vector_push(toks, (void*)tp);   
            goto out;   
        }
        Token* tp;
        tp->type = tok_iden;
        tp->str_d = iden_str;
        vector_push(toks, (void*)tp);
    }
    out:
    return toks;
}

int main()
{
    vector* toks;
    toks = get_tokens("let");
    Token* ftok = (Token*)vector_get(toks, 0);
    switch(ftok->type)
    {
        case tok_let:
            printf("Its a let\n");
            break;
        default:
            printf("Ummm lol nup\n");
            break;
    }
}

这是我的矢量文件:

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

typedef struct d_vector
{
    void **items;
    int capacity;
    int total;
} vector;

void vector_new(vector *v)
{
    v->capacity = 4;
    v->total = 0;
    v->items = malloc(sizeof(void*)*v->capacity);
}

int vector_total(vector *v)
{
    return v->total;
}

static void vector_resize(vector *v, int capacity)
{
    void** items = realloc(v->items, sizeof(void*) * capacity);
    if(items)
    {
        v->items = items;
        v->capacity = capacity;
    }
}

void vector_push(vector *v, void* item)
{
    if(v->capacity == v->total)
    vector_resize(v, v->capacity * 2);
    v->items[v->total++] = item;
}

void vector_set(vector *v, int index, void* item)
{
    if(index >= 0 && index < v->total)
        v->items[index] = item;
}

void* vector_get(vector *v, int index)
{
    if(index >= 0 && index < v->total)
        return v->items[index];
   return NULL;
}

void vector_remove(vector *v, int index)
{
    if(index < 0 || index >= v->total)
        return;

    v->items[index] = NULL;


        for (int i = 0; i < v->total - 1; i++) {
            v->items[i] = v->items[i + 1];
            v->items[i + 1] = NULL;
        }

        v->total--;

        if (v->total > 0 && v->total == v->capacity / 4)
            vector_resize(v, v->capacity / 2);
}

void vector_free(vector *v)
{
    free(v->items);
}

当我运行上面的代码时,我得到了一个 Seg-Fault。 这怎么可能发生?这是gdb的输出:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400656 in vector_new (v=0x1) at vector.h:14
14      v->capacity = 4;

如您所见,当我设置向量容量时,它会出现段错误! 但为什么呢?

【问题讨论】:

    标签: c pointers memory segmentation-fault


    【解决方案1】:

    因为您取消引用垃圾指针而导致段错误:

    vector* get_tokens(char* in)
    {
      vector *toks;
      vector_new(toks);
    

    变量toks 没有分配给任何有意义的东西,只是碰巧浮动的垃圾值。这被传递给vector_new(),它立即取消引用它:

    void vector_new(vector *v)
    {
      v->capacity = 4;
    

    然后 BAM!它爆炸了,因为v 指向不合适的地方。

    在拨打vector_new() 之前尝试mallocvector 或将malloc 放入vector_new() 并让它返回指向新vector 的指针。检查来自malloc() 的返回值也是一个好主意。

    你可以试试这样的:

    vector *vector_new(void)
    {
      vector *v;
      if ( (v = malloc(sizeof(*v))) == NULL ) {
        /* Replace with something appropriate */
        exit(EXIT_FAILURE);
      }
      v->capacity = 4;
      v->total = 0;
      if ( (v->items = malloc(sizeof(*v->items)*v->capacity)) == NULL ) {
        /* Replace with something appropriate */
        exit(EXIT_FAILURE);
      }
      return v;
    }
    

    然后改变你的称呼:

    vector* get_tokens(char* in)
    {
      vector *toks;
      toks = vector_new();
    

    对于每个malloc(),让有一个free()。不要忘记清理这个分配,否则你会泄漏内存:

    void vector_free(vector *v)
    {
      free(v->items);
      free(v);
    }
    

    (您定义了一个vector_free(),但从未调用它。您可能也想考虑这样做。)

    【讨论】:

    • 谢谢!它使 seg-fault 消失了,但现在有一个新的:程序接收信号 SIGSEGV,Segmentation fault。 0x000000000040070e 在vector_push (v=0x1, item=0x7ffffffffe900) at vector.h:37 37 if(v->capacity == v->total)
    • 在您在问题中写的内容中,您实际上从未分配过vector,只是使用指向在任何地方都不存在的vector 的指针来做一些事情。请参阅我使用示例函数 vector *vector_new() 进行的编辑。这会从堆中分配一个vector,以便它可以生存和呼吸。
    • 非常感谢我的好朋友!我的一切都与你的改变一起工作。 :D 再次感谢
    【解决方案2】:

    发生了无效的指针取消引用

    vector *toks;
    vector_new(toks);
    

    应该是

    vector *toks = (vector*)malloc(sizeof(vector));
    vector_new(toks);
    

    【讨论】:

    • 在栈上分配一个vector是不合适的,因为vector的地址就是返回值。
    • 你说得对,这里应该分配新的向量,我会更正我的答案,谢谢。
    • 这是 C。你不必投射 void *
    • 没必要,个人习惯而已。
    猜你喜欢
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    相关资源
    最近更新 更多