'Language'에 해당되는 글 3건

  1. 2007.09.08 malloc? free? new? delete?
  2. 2007.09.03 Age == 17? 17 == Age?
  3. 2007.09.03 int? long?
Tip & Tech2007. 9. 8. 21:54

다음 코드의 결과를 예측해보세요. ^^


#include <iostream>
#include <stdlib.h>
#include <string.h>

using namespace std;

class MyClass
{
public:
    char* name;

    MyClass(void);
    ~MyClass(void);
};

MyClass::MyClass(void)
{
    cout<<"My Class is constructed."<<endl;
    name = (char*)malloc(sizeof(char) * 10);
}

MyClass::~MyClass(void)
{
    free(name);
    name = NULL;
    cout<<"My Class is destroyed."<<endl;
}

int main(void)
{
    MyClass* myClass = (MyClass*)malloc(sizeof(MyClass));
 
    strcpy(myClass->name, "virgo81");

    free(myClass);
    myClass = NULL;

    return 0;
}


.
.
.
.
.
.


C를 먼저 배우시고 C++을 배우신 분들이 쉽게할 수 있는 실수가 위 코드에 있어요.

위 코드의 실행결과는 애석하게도 볼 수 없어요.

왜냐하면 "런타임 오류"가 발생하기 때문이죠.

어느 코드에서 "런타임 오류"가 발생할까요?

범인은 바로! 코드 안에 있습니다.(썰렁;;;)

strcpy(myClass->name, "virgo81");

바로 이 라인에서 발생해요. 할당되지 않은 공간에 복사를 하려하기 때문이죠.

"엥? 생성자에서 분명히 할당하였는데 할당되지 않았다니!!! 거짓말 쟁이!" 라고 하시는 분이 계실거에요.

하지만, 위 코드에서 생성자와 소멸자는 불려지지 않습니다.

malloc 과 free는 생성자를 부르지 않고 단지, 메모리만 할당합니다.

따라서

name = (char*)malloc(sizeof(char) * 10);

위 라인이 실행되었을거 같지만, 실행되지 않았습니다.

그러면 어떻게 하면 좋을까요?

C++로 왔으면 new 와 delete 를 이용하세요.!

아래 코드는 수정된 코드입니다.



#include <iostream>
#include <stdlib.h>
#include <string.h>

using namespace std;

class MyClass
{
public:
    char* name;

    MyClass(void);
    ~MyClass(void);
};

MyClass::MyClass(void)
{
    cout<<"My Class is constructed."<<endl;
    name = new char[10];
}

MyClass::~MyClass(void)
{
    delete [] name;
    name = NULL;
    cout<<"My Class is destroyed."<<endl;
}

int main(void)
{
    MyClass* myClass = new MyClass();
 
    strcpy(myClass->name, "virgo81");

    delete myClass;
    myClass = NULL;

    return 0;
}


어때요? 잘 작동하죠?^^

Posted by virgo81

댓글을 달아 주세요

Tip & Tech2007. 9. 3. 23:17
조건문에서 사람들은 보통 상수를 오른쪽에 놓는다.

C 코드로 예를 들면 아래와 같다.

if(Age == 17) {
// 수행될 문장.
}

==을 =으로 쓰지 않는 한 아무 문제 없는 식이다.

아래와 같은 경우를 생각해보자.

if(Age = 17) {
// 수행될 문장
}

이 역시, 멍청한 컴파일러에게는 아무 문제 없는 식이다.(똑똑한 최신 컴파일러 if 문 안이 무언가 잘못 되었다고 생각하고 자기 의견을 알려준다.)

문제는 우리가 항상 똑똑한 컴파일러를 쓴다는게 아니다.

이런 실수를 줄일려면, 간단한 습관하나만 바꾸면 된다.

상수를 왼쪽에 써보아라.

if(17 == Age) {
// 수행될 문장.
}

아무 문제 없이 잘 작동한다.

if(17 = Age) {
// 수행될 문장.
}

아주 멍청한 컴파일러라도 저정도 문장은 이해하고 에러를 안겨줄 것이다.

당신도 습관을 바꿔보겠는가?? 근데 습관 바꾸는게 생각보다 쉽지 않다~ㅡㅜ




In condition statement, People generally set a constant right side.

For example, C code.

if(Age == 17) {
// Some lines to be executed.
}

If you didn't use = instead of ==, There is no problem.

You can see the other case.

if(Age = 17) {
// Some lines to be executed.
}

Stupid compiler thinks there is no problem. (State of the art compiler might say there is a problem.)

Problem is that you always use state of the art compiler is not true..

Just change your coding style.

Set a constant left side.

if(17 == Age) {
// Some lines to be executed.
}

There is no problem.

if(17 = Age) {
// Some lines to be executed.
}

Even stupid compiler will say there is a problem.

Can you change your coding style?? But, It is hard to change...T.T
Posted by virgo81

댓글을 달아 주세요

Tip & Tech2007. 9. 3. 22:44
오늘은 작은 실수가 프로그램에 큰 오류를 가져오는 경우를 얘기해볼게요.

여러분은 int와 long의 차이점을 아는지요?
아직 int 와 long의 차이점을 모르고 코딩을 하고 있다면,
어쩌면 당신은 아주 위험한 상황에 이르거나,
심각한 오류를 경험하게 될지도 모릅니다.
먼저 int와 long이 어떤 차이를 가지고 있는지
알아본 후, 이 글을 읽어 보세요.

저는 지금 32bit 상위 머신에 32bit 상위 운영체제에
32bit 상위 컴파일러를 쓰고 있습니다.
위와 같은 환경은 저뿐만 아니라 부주의한 프로그래머에게
잠재적인 위험을 가지게 만들었습니다.
어떤 위험인지는 예를 들어서 설명해보겠습니다.

32bit 상위 머신에서 32bit 상위 운영체제에서
32bit 상위 컴파일러에서 만들어진 프로그램이 있습니다.
이 프로그램은 Windows 2000, XP, 2003, Vista에서
아주 정상적으로 작동합니다.
Windows 98에서 동작상의 문제를 발견하기 전까지의
특정한 경우 잘 작동하였습니다.
그러던 어느날.. 비정상적인 작동을 하는
Windows 98이 설치 된 머신을 발견하게 됩니다.
처음에는 그 머신의 개별적인 문제라고 생각 되었습니다.
그러나 어느덧 비정상적인 작동을 하는 Windows 98이 설치된
머신이 많다는 사실을 알게 되었고,
그 버그 수정을 제가 맡게 되었습니다.

그 프로그램은 많은 Windows API를 사용하고 있었습니다.
그 API 중 하나를 예를 들어보겠습니다.

SetViewportExtEx

The SetViewportExtEx function sets the horizontal and vertical extents of the viewport for a device context by using the specified values.

BOOL SetViewportExtEx(

HDC hdc, // handle of device context
int nXExtent, // new horizontal viewport extent
int nYExtent, // new vertical viewport extent
LPSIZE lpSize // original viewport extent
);

이런 기능의 함수 입니다.

처음에는 이 함수가 버그의 원인이라고는 생각하지도 못했습니다.
반환 값도 정상적으로 true 를 반환했기 때문이지요.

저 함수를 쓴 예를 보이죠.
SetViewportExtEx(Hwnd, 50000, 50000, size);

위 함수에 문제가 있나요?
32bit 상위 머신에서 32bit 상위 운영체제에서
32bit 상위 컴파일러를 사용하시는 당신은
아무 문제를 경험하지 못할 것입니다.
이는 잠재적으로 버그를 잡기 힘들게 만들죠.

무엇이 문제인가요?
50000! 50000이란 값이 문제입니다.
32bit 상위 머신에서 32bit 상위 운영체제에서
32bit 상위 컴파일러를 이용하는 우리는
아주 아주 자연스럽게 당연하게
int 를 long 으로 생각하는 경향을 가지게 되었습니다.
이것은 우리만의 작은 소망일 뿐이죠.
32bit 상위 머신에서 32bit 상위 운영체제에서
32bit 상위 컴파일러를 이용하는 우리에게
그 작은 소망은 대체로 이루어 지고 있고요.

그러나 Windows 98 API는 우리의 작은 소망을 철저히 무시하고
int ? short 이네.. 하고.. -17232(맞나요?)를 가지게 되었던 것이죠.

수많은 시행착오와 산수(?)를 한 결과, 위의 버그는 고쳐졌습니다.
그러나 많은 시간이 소요 되었고, 시간적 인적 낭비가 아닐 수 없습니다.

여러분도
int 대신

unsigned long
unsigned short
signed long
signed short

를 쓰길 바라겠습니다.

아마 위 내용들은 각 언어를 배우면서 앞부분에 배웠을겁니다.
이런 기초적인 내용은 그냥 잊고 지나치기 쉽습니다.
그러나 이런 기초적인 내용에서 나오는 오류를
해결하는 것은 기초적이지 않습니다.

여러분 모두를 버그 없는 세상에서 보길 바랍니다.

P.S. 아직도 int 를 쓰고 있습니다; 쉽게 고쳐지지는 않네요.^^;
Posted by virgo81

댓글을 달아 주세요