warning 이 뜨는데, 이유를 알수가 없습니다...T.T

kkojiband의 이미지

일단 코드부터 봐주세요...

Keyboard.h

#ifndef	__KEYBOARD_H__
#define	__KEYBOARD_H__


#include "WaitThread.h"
#include "Interrupt.h"


#define  ...



struct KeyQueue
{
		unsigned short	queue[ MAX_KEY_QUEUE ];

		unsigned short	top, bottom;
};

struct KeyValue
{
		unsigned char	sca;
		unsigned char	led;
		unsigned short	code;
};

<여기에!!!>

void	init_keyboard( void );
void	keyboard_handler( struct InterruptState *is );

struct WaitThread	*insert_keyboard_wait_thread( struct Thread *thread );   <== warning
int			delete_keyboard_wait_thread( struct WaitThread *waitThread );

struct KeyQueue	*init_key_queue( void );

void	push_keycode_in_thread( unsigned short keycode, struct Thread *thread );     <== warning
unsigned short	pop_keycode_in_thread( struct Thread *thread );    <== warning


#endif

여기에서 보면 warning 이라고 표시한 부분들에서,

'struct Thread' declared inside parameter list

라는 에러가 뜹니다...

struct Thread 는 include 로 포함이 되어 있구요,

그리고 더욱 황당한건,

'여기에' 라는 부분에,

struct Thread temp;

이렇게 struct Thread 변수를 하나 선언해두면 컴파일이 제대로 됩니다...--;

요즘 이상한 질문들만 계속 올립니다...죄송합니다...--;

근데 아무리 봐도 왜 warning 이 나는지 알수가 없습니다...T.T

대체 왜 이런걸까요?? 도와주세요~

mach의 이미지

struct Thread를 선언한 헤더도 보여주시지요.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

kkojiband의 이미지

Thread.h

#ifndef	__THREAD_H__
#define	__THREAD_H__


#include "Task.h"
#include "Keyboard.h"


#define	THREAD_MEM_PAGE_START	0x800

#define	INTERRUPT_FLAG			1 << 9



struct Thread
{
		unsigned short	id;

		unsigned short	tick;
		
		struct TaskStateSegment	*tss;

		struct Thread	*prev, *next;

		struct KeyQueue	*keyQueue;

		unsigned char	state;
};


struct Thread	*create_thread( void );
struct Thread	*init_kernel_thread( void *func );


#endif

대체 왜 이런걸까요...T.T

참고로 컴파일은 리눅스 2.4 에서 gcc 2.95 로 하고 있습니다...

이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~

cdpark의 이미지

Keyboard.h는 Thread.h를 부르고, Thread.h는 다시 Keyboard.h를 부르는 순환 include 상태군요. (WaitThread.h에서 Thread.h를 부르겠죠?)

자료구조를 선언하는 부분과 실제 함수 prototype을 선언하는 부분을 분리해서 순환을 끊어주세요.

kkojiband의 이미지

먼저, 답변 감사드립니다~!

제가 구글에서 검색해서 찾아본 결과 아무래도 컴파일러 자체의 버그일 가능성이 제일 높은듯합니다...

근데요...-_-;;;

제가 gcc 3.2, gcc 3.0, gcc 3.03 등 몇가지 받아서 설치를 시도해봤는데요,

잘 되다가 모두다,

... `grep -v '^#' ./libtool-version`

이런 메세지가 뜨면서 멈춰버립니다...

따로 먼저 설치해줘야하는게 있나요? 왜 이럴까요?

이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~

kkojiband의 이미지

제가 컴파일러를 자세히 공부한적이 없어서 확실히는 모르겠지만, 대략적인 원인은 알아낸것같습니다...

컴파일러 자체의 버그같기도하고 뭔가 구조체 해석 방법에 약간 일관성이 없는것 같기도합니다...

컴파일시에 struct가 선언이 되기 전에 와도 되는 것들은,

초기화되지 않은 전역, 정적 변수들 <== 컴파일시에는 공간을 차지 하지 않아서

포인터형으로 선언된 것들 <== 모든 포인터는 4 byte 공간을 차지하니까

나머지 컴파일시에 공간을 차지하는 것들은 모두 struct가 선언이 된 후에 와야 됩니다...

근데 이상한 건, struct 가 선언되기 전에 나온, struct 의 포인터를 인자로 받는 함수원형의 경우에는 위의 에러가 납니다...

에러가 날 이유가 없지않나요?

근데 더 이상한건,

이런 경우 함수원형 앞에 위에서 말한 struct가 선언되기 전에 와도 되는 것들이 하나라도 있으면 함수원형 부분에서 위와 같은 에러가 발생하지 않습니다...

이게 과연 어떤 원칙에 의해 발생하는 문제일까요? 아님 컴파일러의 작은 버그일까요?

제가 생각하기엔 일관성이 없는걸로 봐서는 버그로 생각해야될 것같습니다...

근데, 구글에서 검색해보니 비슷한 경우가 많던데, 최근 gcc 3.2 이상 버젼에서도 같은 문제가 발생하는걸로 봐서는, 버그가 아니고 다른 문제인것 같기도하고...

일단 에러의 원인은 알게되어서 코드를 수정할순있겠지만, 뭔가 찝찝하네요...

고수님들~ 왜 이런지 좀 가르쳐주세요~!!!

이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~

최종호의 이미지

kkojiband wrote:

struct Thread 는 include 로 포함이 되어 있구요,

그리고 더욱 황당한건,

'여기에' 라는 부분에,

struct Thread temp;

이렇게 struct Thread 변수를 하나 선언해두면 컴파일이 제대로 됩니다...--;

혹시 정의하신 것이

struct Thread temp;

가 아니라

struct Thread *temp;

아닌가요?

말씀하신 대로라면

struct Thread temp; <- 이 부분에서 에러가 발생해야 하거든요.

kkojiband의 이미지

에러가 발생을 안하겠죠^^

위에 말씀드린대로 초기화되지 않은 전역변수는 컴파일시에는 따로 공간을 차지 않아서 struct 선언보다 앞에 와도 컴파일러가 봐주는듯(?)합니다...^^;

이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~

lsj0713의 이미지

경고 메시지에 주목할 필요가 있습니다.

'struct Thread' declared inside parameter list

말 그대로 struct Thread가 함수의 파라미터 리스트에서 선언되었다는 뜻입니다.

C에서는 배열이나 구조체를 불완전형(incomplete type)으로 선언할 수 있습니다. 불완전형은 그 대상체의 크기를 알 수 없는 데이터형을 의미합니다. 물론 프로그램이 끝날 때까지 불완전형일 수는 없고, 언젠가는 추가적인 정보가 붙어서 완전한 데이터형을 이루어야만 합니다. 몇가지 예를 "C언어 펀더멘탈"에서 인용하면 다음과 같습니다.

"C언어 펀더멘탈" p.605

typedef struct foo user_type; /* incomplete type */
/* ... */
struct foo { /* 맴버 선언 생략 */ }; /* completed */

"C언어 펀더멘탈" p.608 예제 9-2 상호 참조 구조체의 선언

struct foo {
    int data1;
    struct bar *next1; /* incomplete type */
};
struct bar {
    int data2;
    struct bar *next2;
}; /* completed */

불완전형으로 선언했을 경우에는, 추가적인 정보가 입력되어 완전한 형을 이루기 전까지는 몇가지 한정된 범위에서만 사용할 수 있습니다. 위의 경우처럼 불완전형의 포인터를 사용하는 경우를 예로 들 수 있겠죠.

형 지정자로 미리 정의되지 않은 구조체 공용체 태그 네임이 사용될경우, 그 순간부터 불완전형으로 선언 되는 것이 보통이지만, 에러 메시지로 미루어 보건대 함수의 파라미터 리스트에서 미리 정의되지 않은 구조체 공용체의 태그 네임을 사용할 경우에는 자동으로 불완전형으로 선언해주지 않는 것 같습니다. 정확한건 표준 문서를 뒤져가며 해석해봐야 되겠지만, 저는 지금 바빠서 이만...-_-;;

좀 더 자세한 것은 "C언어 펀더멘탈"(한빛출판사, 전웅 저) 7장 2절 배열 부분(p.393~) 부분을 참고하시길 바랍니다.

최종호의 이미지

kkojiband wrote:
에러가 발생을 안하겠죠^^

위에 말씀드린대로 초기화되지 않은 전역변수는 컴파일시에는 따로 공간을 차지 않아서 struct 선언보다 앞에 와도 컴파일러가 봐주는듯(?)합니다...^^;

그렇지 않을꺼예요.
lsj0713님이 지적하신 대로 incomplete type이 쓰일 수 있는 곳은 제한적입니다.

다음 세 코드를 컴파일 해 보시기 바랍니다.

struct Thread *b;
int func(struct Thread *b);
main()
{
}

struct Thread b;
int func(struct Thread *b);
main()
{
}

int func(struct Thread *b);
main()
{
}

첫번째 코드는 컴파일 오류가 없지만,
두번째 코드는 1행에서 컴파일 *오류*를 발생시키고
세번째 코드는 1행에서 컴파일 *경고*를 발생시킵니다.
세번째 코드의 *경고*가 kkojiband 님이 보신것과 동일한 것이고요.

header 파일에서 타입 선언의 위치가 잘못되거나 include를 잘못하거나해서
해당 함수 프로토타입을 컴파일하는 순간에 struct Thread가
incomplete type 으로 인식된 것으로 판단할 수 있습니다.
즉, 타입 선언이 안 먹혔다는거죠.

문제는 컴파일시의 공간을 차지하는지의 여부가 관건이 아니라
incomplete type이 허용되는 상황에 관한 것으로 보여집니다.

그리고 컴파일러에서 *에러*가 아니라 *경고*를 발생시킨 것은
incomplete type에 대한 포인터를 정의하는 것은 허용되나
일반적으로 그런 경우에는 linked list나 상호 참조 struct 등으로
사용되는 것으로 함수의 파라메터로 incomplete type에 대한 포인터를
쓰는 경우에는 대부분이 해당 struct 선언을 빼먹은
실수일 경우로 판단해서로 보입니다.
(그럼 왜 첫번째 코드에서는 경고가 발생안할까요?)

궁금증 하나!
lsj0713 님과 전웅님은 어떤 관계신가요?
예전같은 경우에 전웅님이 나타나셔야 할 타이밍에
요즘은 lsj0713님이 등장하시는데..
그리고 글 쓰는 스타일이나 reference 다는 스타일이나 같은 분 같은데.. ^^

kkojiband의 이미지

답변 감사드립니다~!

지금까지 설계하나 없이 대충 짜버릇해서 프로그램이 뒤죽박죽이네요...--;

구조체들도 이리 꼬이고 저리 꼬이고...엉망...

그래서 지금과 같이 헤더파일들이 꼬여버려서 문제가 생겼죠...--;

휴...어디서부터 손을 봐야할지...막막...

이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~

lsj0713의 이미지

최종호 wrote:

궁금증 하나!
lsj0713 님과 전웅님은 어떤 관계신가요?
예전같은 경우에 전웅님이 나타나셔야 할 타이밍에
요즘은 lsj0713님이 등장하시는데..
그리고 글 쓰는 스타일이나 reference 다는 스타일이나 같은 분 같은데.. ^^

절대 동일인 아닙니다. ^^;; han.comp.lang.c 에서 활동하는 사람들 글쓰는 스타일이 대체로 그렇습니다. 그리고 제가 전웅님 글보고 C언어 공부해서 그런 영향도 있습니다(2년동안 읽어 왔으니 닮을만도 합니다;;;). 너무 노골적으로 흉내내는 것 같아 전웅님에게 다소 죄송하기도 합니다만, 기술적인 문서의 문체로서는 참으로 마음에 드는 문체인지라...;;;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.