LNK2001에러관련

빌드 작업도중 LNK2001 에러가 발생할때는 헤더파일만 있고 실제 구현파일인 cpp파일이 없을때 자주 일어난다.

#include<stdio.h>
void func(int a, int b);
void main()
{
    func(1, 2);
}
위와 같은 코드가 있다면 컴파일은 무사히 끝난다. 문법적으로 전혀 이상이 없는 코드이기 때문이다.
그러나 func함수는 선언만 되었을뿐 실제 내용이 구현되지 않았으므로 빌드작업을 수행할때 func함수의 내용을 찾지 못하여 에러를 발생시킨다. 이런 경우 func함수의 내용을 구현해주면 해결된다.

by dolbak | 2008/07/15 23:32 | 프로그래밍 | 트랙백 | 덧글(0)

디버깅시 단축키모음

브레이크포인트를 설정하거나 삭제하는 <F9>

( 처음에는 프로그램의 시작위치부터.. ) 다음 브레이크포인트까지 계속 진행하는 <F5>

명령어 다음으로 진행하는 ( 한 줄을 실행하는 ) <F10>

명령어의 안쪽으로 진행하는 ( 함수 호출부로 진입하는 ) <F11>

명령어의 바깥쪽으로 진행하는 ( 함수 외부로 벗어나는 ) <Shift + F11>

현재의 프로그램카운터의 위치에서 커서의 현재 위치까지 실행하는 <Ctrl + F10>

디버그 모드를 종료하는 <Shift + F5>

 

<자주 사용하는 단축키>

에러나 워닝이 발생했을 경우에 커서를 순서대로 점프시켜서 문제가 발생한 라인으로 이동해주는 <F4 나 shift + F4>


복사하기 <ctrl + c>
잘라내기 <ctrl + x>
붙여넣기 <ctrl + v>
실행취소 <ctrl + z>
다시실행 <ctrl + y>
열기  <ctrl + o>
저장하기 <ctrl + s>
새로만들기 <ctrl + n>
찾기  <ctrl + f>
찾아바꾸기 <ctrl + h>
프린트하기 <ctrl + p>
모두선택 <ctrl + a>

 

점진적 정방향 찾기 <ctrl + i>
점진적 역방향 찾기 <ctrl + shift + i>

라인 이동하기  <ctrl + g>
리소스 추가  <ctrl + r>
간편찾기  <ctrl + d>
한줄잘라내기  <ctrl + l>
브레이크포인트목록 <ctrl + b, alt + f9>

by dolbak | 2008/07/14 00:03 | 프로그래밍 | 트랙백 | 덧글(0)

가상함수관련

클래스내에 virtual키워드를 사용한 함수를 가상함수라고 한다.
클래스내에 가상함수가 단 하나라도 있다면 Vtable이라는 테이블을 만들어 함수의 위치를 참조한다.
따라서 메모리공간을 더 차지하고 가상테이블을 한번 거쳐감으로 인해 속도도 상대적으로 저하된다는 단점이 있다.

by dolbak | 2008/07/11 03:46 | C++ | 트랙백 | 덧글(0)

객체의 멤버함수의 위치

#include<iostream>
using std::cout;
using std::endl;

class AAA
{
private:
     int a;
public:
 AAA(int val)
 {
      this -> a = val;
 }
 void Add()
 {
      a++;
 }
};

void main()
{
     AAA a1(10);
     AAA a2(20);

     a1.Add();
     a2.Add();
}
AAA클래스내부에 a라는 정수형 멤버변수와 Add함수가 정의되어 있고 정수값을 인자로 전달받아 a에 대입할수있는 생성자가 정의되어 있다. 코드만 보면 클래스내부에 멤버변수와 멤버함수가 같이 있는것처럼 보이지만 사실 객체가 생성될때 멤버함수는 메모리의 특정부분에 올려져있고 각 객체가 그 영역을 참조하여 멤버함수를 공유하는 형태를 취한다.
그 과정에서 클래스 내부의 멤버함수는 다음과 같이 변한다.

void Add(AAA* temp)
{
    temp->a++;
}

이렇게 하나의 함수를 각 객체가 공유하여 프로그램이 조금 더 효율적으로 된다.

by dolbak | 2008/07/11 03:30 | C++ | 트랙백 | 덧글(0)

virtual소멸자의 필요성

#include<iostream>
using std::cout;
using std::endl;

class AAA
{
private:
     char *str1;
public:
     AAA(char *_str1);
     virtual ~AAA();
     virtual void Show() const;
};
AAA::AAA(char *_str1)
{
     str1 = new char[strlen(_str1)+1];
     strcpy(str1, _str1);
}
AAA::~AAA()
{
     cout << "AAA소멸자 호출" << endl;
     delete []str1;
}
void AAA::Show() const
{
     cout << str1 << ' ';
}

class BBB : public AAA
{
private:
     char *str2;
public:
     BBB(char *_str1, char *_str2);
     ~BBB();
     void Show() const;
};
BBB::BBB(char *_str1, char *_str2):AAA(_str1)
{
     str2 = new char[strlen(_str2)+1];
     strcpy(str2, _str2);
}
BBB::~BBB()
{
     cout << "BBB소멸자 호출" << endl;
     delete []str2;
}
void BBB::Show() const
{
     AAA::Show();
     cout << str2 << endl;
}
void main()
{
     BBB *p1 = new BBB("Hello", "World");
     AAA *p2 = new BBB("I Love", "C++");

     p1->Show();
     p2->Show();

     delete p1;
     delete p2;
}
메인함수내부에서 BBB클래스타입의 포인터가 BBB객체를 가리키고, AAA클래스타입의 포인터도 BBB객체를 가리킨다.
마지막부분의 delete부분에서 각각의 포인터를 해제하는 부분이 있는데 만약 virtual 키워드를 사용하지 않으면 문제가 생긴다.
BBB객체포인터의 관점에서 봤을때는 당연히 BBB객체의 소멸자가 보이므로 BBB객체의 소멸자를 호출하고 BBB클래스가 상속하고 있는 AAA클래스의 소멸자도 호출하기 때문에 B클래스의 소멸자, A클래스의 소멸자가 차례로 호출되어 모든 메모리가 반환이 되어 p1포인터를 해제하는것은 문제가 없다.

하지만, p2객체는 BBB객체를 가리키고있지만 타입이 AAA이므로 AAA의 관점에서 바라보게된다.
따라서 delete문을 만나는 순간 AAA의 소멸자를 호출하고 프로그램이 종료되기 때문에 BBB클래스의 소멸자가 호출되지 않는 현상이 일어나 메모리누수현상이 발생하게 된다.

이런 현상을 방지하기위해 Base클래스의 소멸자에 virtual 키워드를 사용함으로써 결과적으로 모든 소멸자를 호출하게 해야한다.

by dolbak | 2008/07/10 23:45 | C++ | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶