Create TOC

2000년 11월 16일

Linux 시스템 이전하기

이 문서는 구형 시스템에서 새 시스템으로 사용하던 Linux환경을 그대로 이전하는 방법을 설명한다.

새 시스템 준비

  1. 구형 시스템에 새 시스템에 붙일 하드 디스크를 연결한다.
  2. 파티션을 나누고 mkfs 를 이용해서 파일 시스템을 준비한다.

데이타 백업

  1. 새 파티션을 mount 한다. /mnt/new 로 mount 했다고 가정한다.
  2. rsync 명령을 사용해서 기존 파티션의 내용을 복사한다. rsync --recursive --times --perms --owner --group --links --hard-links --one-file-system -stats 원본 경로 /mnt/new 원본 경로는 /dev를 제외한 나머지를 하나 씩 넣어준다. 이런 식으로 /dev를 제외한 파티션을 복사한다.
  3. /dev는 아래와 같이 복사한다. rsync --recursive --times --perms --owner --group --links --hard-links --one-file-system -stats /dev/.static/dev /mnt/new/dev/.static/dev
  4. /mnt/new/etc/lilo.conf를 새 시스템에 맞게 편집한다.

lilo 준비

  1. 새 하드디스크를 새로운 시스템에 설치한 다음 debian 설치 CD로 부팅해서 파티션 나누는 화면까지 진행한다.
  2. 관리 콘솔로 들어가서 새 부팅 파티션을 mount 한다. 이 문서에서는 /mnt/new 에 mount 했다고 가정한다.
  3. chroot /mnt/new 로 root를 변경한다.
  4. mknod 명령으로 필요한 hdxx 장치를 만들어준다.
  5. /sbin/lilo 명령으로 lilo를 재설치한다.
  6. dpkg-reconfigure linux-image-xxxxx 명령으로 부팅 용 ramdisk를 만든다.
  7. mknod로 만들었던 장치를 제거한다.
  8. 시스템을 새 하드로 부팅한다.

변경된 하드웨어 설정

  1. 사운드는 ''alsaconf''를 이용해서 다시 잡는다.
  2. X-windows는 새 시스템에 맞게 수정한다.
  3. lan의 경우 새 lan 카드가 eth1 로 잡히는 경우가 있다. 이때는 /etc/udev/rules.d/z25_persistent-net.rules 파일을 편집해서 옛 시스템의 lan 카드 정보를 지우고 새 lan 카드를 eth0가 되도록 수정한다.

2000년 5월 26일

gdb

조건

gdb로 디버깅하기 위해서는 gcc에 -g 옵션을 주고 컴파일해야 한다.

실행

gdb <실행파일명>

종료

quit

변수값 확인

print 변수명

Break/Watchpoints

breakpoint 설정

간단 설정

break <줄번호|함수명>

조건부 설정

break <줄번호> if <조건>

이미 설정된 breakpoint에 조건을 설정하려면 아래와 같이 하면 된다.

condition <break 번호> <조건>

breakpoint 목록 보기

info break

watchpoint 설정

watch <변수명|조건>

한줄씩 실행

한줄씩 실행. 함수 호출시 함수 내부로 들어가지 않는다.

next or n

한줄씩 실행. 함수 호출시 함수 내부로 들어간다.

step or s

계속 실행

continue

Stack trace

stack 출력

bt

출력 형식은 아래와 같다.

#frame번호 주소 in 함수명(인자) at 파일명:줄번호

예)

(gdb) bt
#0  0x80483ea in sum (a=8, b=8) at main.c:7
#1  0x8048435 in main (argc=1, argv=0xbffff9c4) at main.c:21

frame 이동

frame <frame번호>
up or down

지역변수 확인

info locals

예) backtrace 에서 특정 stack의 지역변수를 확인할때?

(gdb) frame 1
(gdb) info locals

Attach Process

gdb <실행파일명> <pid>

Palm/POSE와 gdb를 이용한 디버깅

prc-tools를 사용하면 m68k-palm-gdb를 사용해서 디버깅을 해야 한다.

디버깅을 위한 빌드

-g 옵션을 이용해 빌드한다.

# m68k-palmos-gcc -g -c hello.c -o hello.o
# m68k-palmos-gcc -g hello.o -o hello

이렇게 빌드하면 hello.prchello가 생성된다.

POSE 실행

POSE를 실행한다.

gdb 실행 및 설정

아래와 같이 m68k-palm-gdb를 실행한다.

# m68k-palmos-gdb hello
GNU gdb 5.3
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Thpe "show copyping" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
this GDB was configured as "--host=i686-pc-cygwin --target=m68k-palmos"...
(gdb)

gdb prompt 에서 아래와 같이 입력한다.

(gdb) target pilot localhost:6414
Remote debugging under PalmOS using localhost:6414
Waiting... (Press Ctrl-C to connect to halted machine)

디버깅

위 단계를 모두 거쳤으면 POSE에 hello.prc 를 설치하고 실행한다. hello.prc를 실행하는 순간 gdb에 아래와 같은 화면이 나온다.

Program received signal SIGSTOP, Stopped (signal).
0x00045888 in PilotMain (cmd=3, cmdPBP=0xa2260000, launchFlags=68) at hello.c:20
20 {
(gdb)

이제 디버깅을 하면 된다.

2000년 5월 15일

C++/Virtual Destructor

아래와 code를 보자.

class Sample {
public:
 Sample() { cout << "Sample" << endl; }
 ~Sample() { cout << "~Sample" << endl; }

};

class Derived : public Sample {
public:
 Derived() { cout << "Derived" << endl; }
 ~Derived() { cout << "~Derived" << endl; }
};


int main(int argc, char **argv)
{
 Sample *p = new Derived;

 delete p;
 return 0;
}

수행결과는 어떨까? 아마도

Sample
Derived
~Derived
~Sample

가 되어야 할 것처럼 보인다. 하지만 실제 수행해보면

Sample
Derived
~Sample

Derived의 destructor가 호출되지 않는 것을 볼 수 있다. 그 이유는 포인터 p는 Sample class 형 포인터 이기 때문에 Derived의 destructor을 알지 못한다. 따라서 위에 delete p 할 때 Sample의 destructor만을 호출하게 된다.

이 문제를 해결하기 위해서는 Simple class 에서 destructor 선언시 virtual 을 사용해야 한다.

virtual ~Sample() { cout << "~Sample" << endl; }

2000년 3월 8일

GCC

따로 찾기 귀찮아서 웹사이트에서 긁은 정보(주로 GCC 3.2 매뉴얼)를 모았습니다.

Standard Predefined Macros

__FILE__

This macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the short name specified in #include or as the input file name argument. For example, "/usr/local/include/myheader.h" is a possible expansion of this macro.
__LINE__
This macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it's a pretty strange macro, since its "definition" changes with each new line of source code.
__DATE__
This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left.
__TIME__
This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like "23:59:01".
__STDC__
In normal operation, this macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C. If GNU CPP is used with a compiler other than GCC, this is not necessarily true; however, the preprocessor always conforms to the standard, unless the -traditional option is used. This macro is not defined if the -traditional option is used. On some hosts, the system compiler uses a different convention, where __STDC__ is normally 0, but is 1 if the user specifies strict conformance to the C Standard. GNU CPP follows the host convention when processing system header files, but when processing user files __STDC__ is always 1. This has been reported to cause problems; for instance, some versions of Solaris provide X Windows headers that expect __STDC__ to be either undefined or 1. You may be able to work around this sort of problem by using an -I option to cancel treatment of those headers as system headers. See Invocation.
__STDC_VERSION__
This macro expands to the C Standard's version number, a long integer constant of the form yyyymmL where yyyy and mm are the year and month of the Standard version. This signifies which version of the C Standard the compiler conforms to. Like __STDC__, this is not necessarily accurate for the entire implementation, unless GNU CPP is being used with GCC. The value 199409L signifies the 1989 C standard as amended in 1994, which is the current default; the value 199901L signifies the 1999 revision of the C standard. Support for the 1999 revision is not yet complete. This macro is not defined if the -traditional option is used, nor when compiling C++ or Objective-C.
__STDC_HOSTED__
This macro is defined, with value 1, if the compiler's target is a hosted environment. A hosted environment has the complete facilities of the standard C library available.
__cplusplus
This macro is defined when the C++ compiler is in use. You can use __cplusplus to test whether a header is compiled by a C compiler or a C++ compiler. This macro is similar to __STDC_VERSION__, in that it expands to a version number. A fully conforming implementation of the 1998 C++ standard will define this macro to 199711L. The GNU C++ compiler is not yet fully conforming, so it uses 1 instead. We hope to complete our implementation in the near future.

Common Predefined Macros

The common predefined macros are GNU C extensions. They are available with the same meanings regardless of the machine or operating system on which you are using GNU C. Their names all start with double underscores.

__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__

These macros are defined by all GNU compilers that use the C preprocessor: C, C++, and Objective-C. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. They are defined only when the entire compiler is in use; if you invoke the preprocessor directly, they are not defined. __GNUC_PATCHLEVEL__ is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have). If all you need to know is whether or not your program is being compiled by GCC, you can simply test GNUC. If you need to write code which depends on a specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased (which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write it like this:
/* Test for GCC > 3.2.0 */
#if __GNUC__ > 3 || \
    (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
                       (__GNUC_MINOR__ == 2 && \
                        __GNUC_PATCHLEVEL__ > 0))
Another approach is to use the predefined macros to calculate a single number, then compare that against a threshold:
#define GCC_VERSION (__GNUC__ * 10000 \
                     + __GNUC_MINOR__ * 100 \
                     + __GNUC_PATCHLEVEL__)
...
/* Test for GCC > 3.2.0 */
#if GCC_VERSION > 30200
Many people find this form easier to understand.
__OBJC__
This macro is defined, with value 1, when the Objective-C compiler is in use. You can use __OBJC__ to test whether a header is compiled by a C compiler or a Objective-C compiler.
__GNUC__
The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ && __cplusplus).
__STRICT_ANSI__
GCC defines this macro if and only if the -ansi switch, or a -std switch specifying strict conformance to some version of ISO C, was specified when GCC was invoked. It is defined to 1. This macro exists primarily to direct GNU libc's header files to restrict their definitions to the minimal set found in the 1989 C standard.
__BASE_FILE__
This macro expands to the name of the main input file, in the form of a C string constant. This is the source file that was specified on the command line of the preprocessor or C compiler.
__INCLUDE_LEVEL__
This macro expands to a decimal integer constant that represents the depth of nesting in include files. The value of this macro is incremented on every #include directive and decremented at the end of every included file. It starts out at 0, it's value within the base file specified on the command line.
__VERSION__
This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it can be counted on to contain at least the release number.
__OPTIMIZE__ __OPTIMIZE_SIZE__ __NO_INLINE__
These macros describe the compilation mode. __OPTIMIZE__ is defined in all optimizing compilations. __OPTIMIZE_SIZE__ is defined if the compiler is optimizing for size, not speed. __NO_INLINE__ is defined if no functions will be inlined into their callers (when not optimizing, or when inlining has been specifically disabled by -fno-inline). These macros cause certain GNU header files to provide optimized definitions, using macros or inline functions, of system library functions. You should not use these macros in any way unless you make sure that programs will execute with the same effect whether or not they are defined. If they are defined, their value is 1.
__CHAR_UNSIGNED__
GCC defines this macro if and only if the data type char is unsigned on the target machine. It exists to cause the standard header file limits.h to work correctly. You should not use this macro yourself; instead, refer to the standard macros defined in limits.h.
__REGISTER_PREFIX__
This macro expands to a single token (not a string constant) which is the prefix applied to CPU register names in assembly language for this target. You can use it to write assembly that is usable in multiple environments. For example, in the m68k-aout environment it expands to nothing, but in the m68k-coff environment it expands to a single %.
__USER_LABEL_PREFIX__
This macro expands to a single token which is the prefix applied to user labels (symbols visible to C code) in assembly. For example, in the m68k-aout environment it expands to an _, but in the m68k-coff environment it expands to nothing. This macro will have the correct definition even if -f(no-)underscores is in use, but it will not be correct if target-specific options that adjust this prefix are used (e.g. the OSF/rose -mno-underscores option).
__SIZE_TYPE__ __PTRDIFF_TYPE__ __WCHAR_TYPE__ __WINT_TYPE__
These macros are defined to the correct underlying types for the size_t, ptrdiff_t, wchar_t, and wint_t typedefs, respectively. They exist to make the standard header files stddef.h and wchar.h work correctly. You should not use these macros directly; instead, include the appropriate headers and use the typedefs.
__USING_SJLJ_EXCEPTIONS__
This macro is defined, with value 1, if the compiler uses the old mechanism based on setjmp and longjmp for exception handling.

Function Names as Strings

GCC predefines two magic identifiers to hold the name of the current function. The identifier __FUNCTION__ holds the name of the function as it appears in the source. The identifier __PRETTY_FUNCTION__ holds the name of the function pretty printed in a language specific fashion.

These names are always the same in a C function, but in a C++ function they may be different. For example, this program:

extern "C" {
extern int printf (char *, ...);
}

class a {
 public:
  sub (int i)
    {
      printf ("__FUNCTION__ = %s\n", __FUNCTION__);
      printf ("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
    }
};

int
main (void)
{
  a ax;
  ax.sub (0);
  return 0;
}

gives this output:

__FUNCTION__ = sub
__PRETTY_FUNCTION__ = int  a::sub (int)

The compiler automagically replaces the identifiers with a string literal containing the appropriate name. Thus, they are neither preprocessor macros, like __FILE__ and __LINE__, nor variables. This means that they catenate with other string literals, and that they can be used to initialize char arrays. For example char here = "Function " __FUNCTION__ " in " __FILE__; On the other hand, #ifdef __FUNCTION__ does not have any special meaning inside a function, since the preprocessor does not do anything special with the identifier __FUNCTION__.

Note that these semantics are deprecated, and that GCC 3.2 will handle __FUNCTION__ and __PRETTY_FUNCTION__ the same way as __func__. __func__ is defined by the ISO standard C99:

The identifier __func__ is implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing function. This name is the unadorned name of the function. By this definition, __func__ is a variable, not a string literal. In particular, __func__ does not catenate with other string literals.

In C++, __FUNCTION__ and __PRETTY_FUNCTION__ are variables, declared in the same way as __func__.

Macros with a Variable Number of Arguments.

In the ISO C standard of 1999, a macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function. Here is an example:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

Here ... is a variable argument. In the invocation of such a macro, it represents the zero or more tokens until the closing parenthesis that ends the invocation, including any commas. This set of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears. See the CPP manual for more information.

GCC has long supported variadic macros, and used a different syntax that allowed you to give a name to the variable arguments just like any other argument. Here is an example:

#define debug(format, args...) fprintf (stderr, format, args)

This is in all ways equivalent to the ISO C example above, but arguably more readable and descriptive.

GNU CPP has two further variadic macro extensions, and permits them to be used with either of the above forms of macro definition.

In standard C, you are not allowed to leave the variable argument out entirely; but you are allowed to pass an empty argument. For example, this invocation is invalid in ISO C, because there is no comma after the string:

debug ("A message")

GNU CPP permits you to completely omit the variable arguments in this way. In the above examples, the compiler would complain, though since the expansion of the macro still has the extra comma after the format string.

To help solve this problem, CPP behaves specially for variable arguments used with the token paste operator, ##. If instead you write

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

and if the variable arguments are omitted or empty, the ## operator causes the preprocessor to remove the comma before it. If you do provide some variable arguments in your macro invocation, GNU CPP does not complain about the paste operation and instead places the variable arguments after the comma. Just like any other pasted macro argument, these arguments are not macro expanded.

System별 predefine

Generated with gcc -E -dM:

Vaxstation

#define __vax__ 1
#define __vax 1
#define __unix 1
#define __unix__ 1
#define vax 1
#define __GNUC__ 2
#define unix 1

Linux (i386)

#define __linux__ 1
#define linux 1
#define __i386__ 1
#define __i386 1
#define i386 1
#define __unix 1
#define __unix__ 1
#define __GNUC__ 2
#define __linux 1
#define unix 1

NetBSD (i386)

#define __i386__ 1
#define __NetBSD__ 1
#define __i386 1
#define i386 1
#define __unix 1
#define __unix__ 1
#define __GNUC__ 2
#define unix 1

NetBSD (sparc)

#define __GCC_NEW_VARARGS__ 1
#define __NetBSD__ 1
#define __sparc 1
#define sparc 1
#define __unix 1
#define __unix__ 1
#define __GNUC__ 2
#define __sparc__ 1
#define unix 1

Decstation

#define __LANGUAGE_C 1
#define R3000 1
#define __SYSTYPE_BSD__ 1
#define SYSTYPE_BSD 1
#define __host_mips 1
#define ultrix 1
#define __MIPSEL__ 1
#define __ANSI_COMPAT 1
#define __MIPSEL 1
#define ___SYSTYPE_BSD 1
#define __mips__ 1
#define __mips 1
#define __host_mips__ 1
#define MIPSEL 1
#define __R3000__ 1
#define __ultrix__ 1
#define host_mips 1
#define __SYSTYPE_BSD 1
#define ___SYSTYPE_BSD__ 1
#define mips 1
#define __LANGUAGE_C__ 1
#define __unix 1
#define __R3000 1
#define __unix__ 1
#define __bsd4_2 1
#define __bsd4_2__ 1
#define __GNUC__ 2
#define __ultrix 1
#define LANGUAGE_C 1
#define _SYSTYPE_BSD 1
#define bsd4_2 1
#define unix 1

RS-6000

#define ___AIX 1
#define ___IBMR2__ 1
#define _AIX 1
#define ___AIX32 1
#define __CHAR_UNSIGNED__ 1
#define ___IBMR2 1
#define ___AIX__ 1
#define ___AIX32__ 1
#define _AIX32 1
#define __GNUC__ 2
#define _IBMR2 1

Sun (Solaris)

#define __GCC_NEW_VARARGS__ 1
#define __sparc 1
#define __svr4__ 1
#define __sun 1
#define sparc 1
#define __sun__ 1
#define __unix 1
#define __unix__ 1
#define sun 1
#define __GNUC__ 2
#define __sparc__ 1
#define unix 1

Sun (SunOS)

#define __GCC_NEW_VARARGS__ 1
#define __sparc 1
#define __GNUC_MINOR__ 5
#define __sun 1
#define sparc 1
#define __sun__ 1
#define __unix 1
#define __unix__ 1
#define sun 1
#define __GNUC__ 2
#define __sparc__ 1
#define unix 1

SGI

#define sgi 1
#define __EXTENSIONS__ 1
#define _SVR3 1
#define mips 1
#define unix 1

HPUX

#define hp9k8 1
#define __hppa 1
#define __hpux 1
#define __hpux__ 1
#define hp9000s800 1
#define PWB 1
#define _PA_RISC1_1 1
#define __hp9000s700 1
#define __hp9000s800 1
#define __PWB__ 1
#define __GNUC_MINOR__ 7
#define hppa 1
#define hpux 1
#define _HPUX_SOURCE 1
#define __hp9k8__ 1
#define __hppa__ 1
#define __unix 1
#define __unix__ 1
#define __hp9k8 1
#define __GNUC__ 2
#define __hp9000s800__ 1
#define __PWB 1
#define unix 1

Minimum and Maximum Operators in C++

It is very convenient to have operators which return the "minimum" or the "maximum" of two arguments. In GNU C++ (but not in GNU C),

a < b

is the minimum, returning the smaller of the numeric values a and b;

a > b

is the maximum, returning the larger of the numeric values a and b. These operations are not primitive in ordinary C++, since you can use a macro to return the minimum of two things in C++, as in the following example.

#define MIN(X,Y) ((X) < (Y) ? : (X) : (Y))

You might then use int min = MIN (i, j); to set min to the minimum value of variables i and j.

However, side effects in X or Y may cause unintended behavior. For example, MIN (i++, j++) will fail, incrementing the smaller counter twice. A GNU C extension allows you to write safe macros that avoid this kind of problem (see Naming an Expression's Type). However, writing MIN and MAX as macros also forces you to use function-call notation for a fundamental arithmetic operation. Using GNU C++ extensions, you can write int min = i < j; instead.

Since < and > are built into the compiler, they properly handle expressions with side-effects; int min = i++ < j++; works correctly.

GnuPG

목차