C代码中的错误

时间:2012-03-01 13:14:18

标签: c

我为我的项目编写了以下代码。代码分散在各种文件中并且很长,因此我发布了最小代码。

#include<stdio.h>
#include<stdbool.h>
struct TwoPoint
{
    int width;
    int value;
};

struct Module 
{
    int categ;
    void *ptr;
};

struct Rect
{
    struct TwoPoint val;
    struct TwoPoint val_new;
    bool is_changed;
};

struct S
{
    int numInstances;
    struct Module instances[20];
    struct Rect RectList[40];
    int numRect;
}s1;

struct Test
{
    int categ;
    struct Rect state;
};

struct TwoPoint initPVal(int v,int w)
{
struct TwoPoint temp;
temp.value=v;
temp.width=w;
return temp;
}
int getValue(struct TwoPoint *b)
{
    return (b->value);
}

struct TwoPoint get(struct Rect *r)
{
    return (r->val);
}

void initialize()
{
     s1.numInstances=0;
     s1.numRect=0;
}

void addRect(struct Rect *r)
{
     if(s1.numRect<40)
     {
     s1.RectList[s1.numRect].val=r->val;
     s1.RectList[s1.numRect].val_new=r->val_new;
     s1.RectList[s1.numRect].is_changed=r->is_changed;
     s1.numRect++;
     }
}

struct Rect initRect(struct TwoPoint initval) 
{
struct Rect temp;
struct TwoPoint tempP;
tempP=initPVal(0,0);
temp.val=initval;
temp.val_new=tempP;
temp.is_changed=false;
addRect(&temp);
return temp;
}

void copy(struct Rect *r)
{
    if(r->is_changed)
    {
    r->val= r->val_new;
    r->is_changed=false;
    }
}
void copyRect()
{
   int i=0;
   for(i=0;i<s1.numRect;i++)
   {    
    copy(&s1.RectList[i]);
   }
}

void setInstance(struct Module *m)
{
    s1.instances[s1.numInstances].categ=m->categ;
    s1.instances[s1.numInstances].ptr=m->ptr;
    s1.numInstances++;
    if (s1.numInstances >= 20)
    {
    printf("Too many instances");
    }
}

void setModule(struct Test *t)
{
    struct Module m;
    m.categ=t->categ;
    m.ptr=&t;
    setInstance(&m);
}



void init(struct Test *t)
{
    t->categ=2;
    struct Rect tr;
    struct TwoPoint tb1=initPVal(0,5);
    tr=initRect(tb1);
    t->state=tr;
}

void actions(struct Test *t)
{
    struct TwoPoint tb=get(&t->state);
    int y=getValue(&tb);
    printf("%d\n",y);
    unsigned int x=getValue(&tb);
    printf("%u\n",x);
    switch(y)
    {
      ....
    }
}

void initS() 
{   
     init(s1.instances[0].ptr);
}   

void act() 
{       
     actions(s1.instances[0].ptr);
}

void setup()
{
    struct Test t;
    initialize();
    init(&t);
    setModule(&t);
}

void run()
{ 
    initS();
    act();
    copyRect();
}


int main()
{
    printf("foo\n");
    setup();
    printf("bar\n");
    run();
    return 0;
}

有两个错误:

  1. 通过initS()函数调用init()函数会导致Stack Overdumped错误,而我在setup()中调用它时工作正常。我认为Call正确,因为正在执行action()函数。
  2. 第二个问题是actions()函数。当我计算y的值用作切换条件而不是值为0,1,2或3时,它是我在尝试调试时通过打印找到的一些内存地址。

2 个答案:

答案 0 :(得分:2)

问题是:

void setup()
{
    struct Test t;
    initialize();
    init(&t);
    setModule(&t);
}

Test结构分配为本地堆栈变量,然后将其地址分配给稍后访问的某个变量。访问此变量的下一次是(init):

void init(struct Test *t)
{
    t->categ=2;
    struct Rect tr;
    struct TwoPoint tb1=initPVal(0,5);
    tr=initRect(tb1);

    t->state = tr;
}

此时指针指向已超出范围的变量,导致未定义的行为。实际发生的是由于尝试的结构分配,堆栈被粉碎。这就是为什么它也很难获得回溯的原因。

一种解决方案是使用malloc分配内存,如下所示:

void setup()
{
    struct Test * t = malloc(sizeof (struct Test));
    initialize();
    init(t);
    setModule(t);
}

存在另一个问题,即setModule中的语义错误:

void setModule(struct Test *t)
{
    struct Module m;
    m.categ=t->categ;
    m.ptr=&t;
    setInstance(&m);
}

m.ptr=&t实际应该是m.ptr = t。打算指定一个指向Test结构的指针。相反,发生的事情是指定了一个指向Test结构(指向Test结构的双指针)指针的堆栈变量的地址。

答案 1 :(得分:1)

我假设您显示run()调用actions()的位置,实际上是调用act(),因为前一个函数需要一个参数。

setModule()中,您有

m.ptr=&t;

其中t已经是指向struct Test的指针。所以你在m.ptr中存储的是指向结构的指针。在act()中,将此存储的指针传递给actions(),它指向一个结构的指针,而不是指向结构的指针。因此,当函数取消引用指针并将结果视为struct Test时,它会得到谁知道什么。

最有可能的是,您只想将setModule()中的行更改为

m.ptr=t;

因为t已经是指针。但也许有一些原因你真的想要一个指针指针,在这种情况下你需要更改使用指针正确使用它的代码。这里的一个问题是编译器无法帮助您确保类型安全,因为您将指针存储为void *并隐式将其转换为其他类型。

作为旁注,您似乎比我想象的那样使用&运算符。在我看来,你的函数是只读的,例如getValue(),应该只是一个struct参数,而不是一个结构的指针,然后你就不需要那么多地获取变量的地址。但也许这是一个品味问题。