2012-03-01 4 views
0

내 프로젝트에 다음 코드를 작성했습니다. 코드는 여러 파일에 걸쳐 흩어져 있으므로 최소한의 코드 만 게시하고 있습니다.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; 
} 

이 두 가지 오류가 있습니다 : 나는() 설정에라고하면서 잘 작동하는 반면 initS를 통해 호출

  1. 초기화() 함수() 함수는 Overdumped 오류를 스택에 이르게. 액션() 함수가 실행될 때 호출이 정확하다고 생각합니다.
  2. 두 번째 문제는 actions() 함수에 있습니다. 내가 값을 0, 1, 2 또는 3 대신 스위치 조건으로 사용하기 위해 y 값을 계산할 때 디버깅하는 동안 인쇄하여 찾은 일부 메모리 주소입니다.
+0

당신은'setup()'또는'action()'이라는 함수를 게시하지 않았습니다. –

+0

또한 copy() 및 initRect()가 누락 된 것 같습니다. BTW 컴파일러는 경고 레벨을 최대로 설정할 경우 (gcc의 -Wall, -pedantic) – wildplasser

+0

뚜렷한 것을 확인 했습니까? 예 :'s1.instances [0] .ptr' –

답변

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 구조체에 대한 이중 포인터)에 대한 포인터를 보유하고있는 스택 변수의 주소가 할당되었습니다.

+0

새 코드도 문제없이 컴파일되고 실행됩니다. –

+0

하지만 내 컴퓨터에서 실행하면 오류가 발생합니다. 코드 패드에서 코드를 실행했는데 거기에도 오류가있었습니다. http://codepad.org/SRjsWVX5 –

+0

내 컴퓨터와 코드 패드에서 동일한 오류가 계속 발생합니다. http://codepad.org/dFNo3UF7 –

1

난 당신이 run()actions()를 호출 보일 것 이전 함수는 매개 변수를 필요로하기 때문에, 실제로, act()를 호출 있으리라 믿고있어. t 이미 struct Test에 대한 포인터입니다 setModule()에서

, 당신은

m.ptr=&t; 

있습니다. 그래서 m.ptr에 저장 한 것은 struct에 대한 포인터에 대한 포인터입니다. act()에서이 저장된 포인터를 actions()에 전달합니다.이 포인터는 구조체에 대한 포인터가 아니라 구조체에 대한 포인터를 필요로합니다. 따라서 함수가 포인터를 역 참조하고 결과를 struct Test으로 처리하면 누가 알고 있는지를 알게됩니다.

대부분의 경우, 당신은 단순히 t 이후

m.ptr=t; 

setModule()의 라인을 변경하려면 이미 포인터입니다. 그러나 아마도 포인터에 대한 포인터를 갖고 싶다면 어떤 이유로 포인터를 사용하는 코드를 바꿔서 포인터를 올바르게 사용해야 할 필요가있을 것입니다. 여기서 문제는 포인터를 void *으로 저장하고 암시 적으로 다른 유형으로 변환하기 때문에 컴파일러가 형식 안전을 보장 할 수 없다는 것입니다.

보조 노트로 보니 평소와 다름없이 & 연산자를 사용하는 것 같습니다. 읽기 전용 인 함수 (예 : getValue()은 단순히 구조체에 대한 포인터가 아닌 struct 매개 변수를 취해야하며 변수의 주소를 너무 많이 얻을 필요는 없습니다. 그러나 이것은 아마도 미각의 문제입니다.