[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Error when executing shell command in "Cygwin make"
Here is the case.

path=c:\cygwin\bin; (...omitted... );; (...omitted...)

Take you attention to ';;' - two consecutive semicolon.

In above path environment, executable binaries like 'cp', 'mkdir' that are in 'c:\cywin\bin', works well. But, shell command like 'cmd' raise error something like "command not found".

After removing ';;' - consecutive semicolon (empty path) -, all works well.

So, here is my inference.

"Cywin make" executes command by following order.
  1. searching path environment to file executable binary.
  2. regards command as 'shell command' and try to execute.

In case that ';;' is appeared in the path, "Cygwin make" cannot recognize path after ';;'. So, executables located in the directory those are before ';;' works well. But, those are not, "Cygwin make" treats it as "shell command" and raises error (there is no shell command like this...).

'Domain > Win32' 카테고리의 다른 글

[Win32][Tips] Creating Window...  (0) 2007.06.27
[Win32] IME Active중 VK Code얻기  (0) 2007.06.25
[Win32] 한글 입력하기  (0) 2007.06.23
[Tips] Cross-Compiling on Windows for Linux  (0) 2007.06.20
[VC][Tips] 2005 express  (0) 2006.04.12

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

RVCT and ADS make long jump be possible by adding veneer. But, interestingly, link tool of RVCT and ADS, added veneer only when jump to the code located in other execution area. So, in the case that long jump to the same-execution-area-code is needed, linker generates "memory relocation error" in ADS and RVCT. That's why we need to classify code and put them into several execution area.

TI's TMS470 adds veneer('Trampoline' in TMS) even if target code of long jump is in same execution area. But TMS470 is very slow... :-(

I have no idea about gnu arm eabi tools...

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Conflicting symbol name with library is not rare.
So, I want suggest my personal opinion to avoid this.

1. Before release code/library, change all symbol name of source code into unique name (random string) with tool.
2. Determine appropriate symbol name that should be exported.
  (There can be two options. (*a)One is "changing exported symbols into agreed name". (*b)The other is "providing header file that includes all exported symbol with recommended name. And user can re-define necessary or conflicting symbol into expected one")

Let's see the example.

 a. (original source code)
  ...
  MY_UINT32 my_name;
  ...
  MY_UINT16 company_name;
  ..

 b. (symbol-changing-tool setting) - change symbol from 'a.'
  ...
  MY_UINT32 => FooRgYaIIkdjdtq40238dkkRkwUTTT00001
  MY_UINT16 => FooRgYaIIkdjdtq40238dkkRkwUTTT00002
  my_name => FooRgYaIIkdjdtq40238dkkRkwUTTT00003
  compay_name => FooRgYaIIkdjdtq40238dkkRkwUTTT00004
  ...

 c. (auto-modified original source code)
  ...
  FooRgYaIIkdjdtq40238dkkRkwUTTT00001 FooRgYaIIkdjdtq40238dkkRkwUTTT00003;
  ...
  FooRgYaIIkdjdtq40238dkkRkwUTTT00002 FooRgYaIIkdjdtq40238dkkRkwUTTT00004;
  ...

-------- (*a) -------------

 d1. agreed name
  MY_UINT32 => UINT32
  MY_UINT16 => UINT16
  my_name => company_name
  company_name => firm_name

 d2(*a). (symbol-changing-too setting) - change symbol from 'c.' based on 'd.'
  FooRgYaIIkdjdtq40238dkkRkwUTTT00001 => UINT32
  FooRgYaIIkdjdtq40238dkkRkwUTTT00002 => UINT16
  FooRgYaIIkdjdtq40238dkkRkwUTTT00003 => company_name
  FooRgYaIIkdjdtq40238dkkRkwUTTT00004 => firm_name

---------- (*b) ---------

 d. (header file that has recommended symbol)
  /*symbol_match.h */
  /*=============== symbol-matching table ================= */
  ...
  #define UINT32 FooRgYaIIkdjdtq40238dkkRkwUTTT00001
  #define UINT16 FooRgYaIIkdjdtq40238dkkRkwUTTT00002
  #define my_name FooRgYaIIkdjdtq40238dkkRkwUTTT00003
  #define company_name FooRgYaIIkdjdtq40238dkkRkwUTTT00004
  ...

--------------------

 e. (Releasable code - base source code for building library)
  ...
  UINT32 company_name;
  ...
  UINT16 firm_name;
  ...

I think this way is worth considering to make very portable library.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

"Design pattern" / "Extream programming" / "내 경험"

"Design pattern" 은 정말 유용하다. 이것은 코드를 좀더 flexible하고 또 건전하게 만든다. 그러나, software의 불변의 진리 중에 하나는, "Software를 soft하게 만들기 위해서는 비용이 든다" 이다. 즉 design pattern을 최대한 많이 적용해서, flexible한 코드를 만든다는 말은, 많은 추가적인 비용이 든다는 말이다. 또한 몇몇 책에서는, 개발자는 이후 변화할 요구사항에 대해 예측하는 것은 매우 어렵기 때문에, 초기부터 너무 flexible한 code를 짜고자 한다면, 이는 결국 project가 끝날 때까지 거의 쓸일이 없는, 쓸데없이 복잡한 구조를 만드는, over-engineering을 하게 된다고 주장한다("Addison Wesley Refactoring to patterns" 참조.). 따라서 Extream programming에서는 현재까지 알려진 요구사항만을 만족시킬 수 있는 최소한의 Flexibility를 가지는 software로 충분하며, 이후 추가되는 요구사항에 대해서는 refactoring을 통해서 계속해서 개선시켜 나갈 것을 권고하고 있다.

그런데, 문제는, 보통의 경우, 요구사항이 바뀌고, 이를 만족시키는 코드를 추가하고, 또 바뀌고, 추가하고... 이를 반복하다가 어느 순간, 이런 작업으로 인한 overhead가 너무 많다고 생각되면, source code refactoring을 하게 되며, 이는 source code의 구조를 바꾸는 큰 일이 된다. 즉, Extream programming에서 주장하듯 꾸준한 refactoring을 통해서, source code의 건전성을 확보하면 된다는 말은, 물론 좋은 말이긴 하다. 그러나 한편, 이는 design pattern을 이용한 "over-engineering"을 피하다가 결국 refactoring을 결정하기 까지, 많은 추가적인 비용을 들이게 되는, 또 다른 형태의 over-engineering을 하게 될 수도 있다..

결론적으로 절대적인 옳고 그름은 없다는 말을 하고 싶다.

개발자가 이후 발생할 요구사항의 변화를 100% 예측하는 것은 분명히 불가능하다. 그러나, 몇몇 부분에 대해서는 예측이 가능할 수도 있다. 그리고 이렇게 예측이 가능한 부분에 대해서도, 단지 현재의 요구사항에 없는 부분이라고 해서 flexible한 design을 적용하지 않는다면, over-engineering을 피하기 위해서, 또 다른 문제를 만들게 되는 폐단을 낳게 된다. (내가 보기에는 이것도 일종의 under-engineering이다. 따라서 이후 이것 또한 under-engineering으로 칭하기로 한다. - 이는 "Addison Wesley Refactoring to patterns" 에서 이야기하는 under-engineering과는 좀 다른 이야기이다.)

즉, flexible해야 한다고 강력하게 예측가능한 부분은 처음부터, 혹은 추가되는 요구사항을 구현하는 초기 부터 flexible하게 만드는 것이 under-engineering으로 발생하는 폐단을 막을 수 있다. 또한 programmer로서의 능력과 영감을 좌우하는 상당부분은 바로, 어떤 부분이 flexible해야 할 것인가? 를 판단하는 능력이 결정한다.

예를 하나 들어보자. (내가 경험한 실례를 가지고 설명한다.)

분산 컴파일을 위한 program을 만든다고 생각하자. 그리고 이 중에서도, network programming부분에 focus를 맞추어서 생각해 보자.
처음에 생각되는 요구사항은, 컴파일 할 파일을 전달하고, 결과로 만들어진 object binary file을 되돌려 받으면 될 것 같다.
그렇게해서, "size(4byte)+data(...)" 의 binary를 보내고 받는 socket function을 짠다. 그런데, programmer로서의 경험은, server-client간 통신은 항상 추가적인 필요가 발생했었고, 지금의 경우도 분명히 추가적인 무언가가 발생할 것이라고 말하고 있다. 그런 이유로, client-server가 network communication을 위한 layer를 만들었고, 단순히 compile을 위한 file과 object만이 아니라, 일반적인 data를 전송할 수 있게, protocol unit manager를 만들었다. 이후 이 두 module은 추가적인 요구사항이 발생할 때, 큰 어려움 없이 feature를 늘리는데 상당히 큰 도움을 주었다.

만약 만들지 않았다면?... 손발이 더욱 고생하지 않았을까?

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Language                     Ratio

-----------------------------------------------------------
Assembler                    1 to 1
Ada                          1 to 4.5
Quick/Turbo Basic            1 to 5
C                            1 to 2.5
Fortran                      1 to 3
Pascal                       1 to 3.5

< Source : Applied Software Measurement (Jones 1991) >

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

'virtual' is runtime-deterministic keyword. But 'inline' is compile-time-deterministic keyword....
I think 'virtual' has priority.... I haven't tested it yet!!! :-)
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

At first, see
 virtual inheritance in wikipedia to know about virtual inheritance.

There are lots of articles about this. So, I am adding 'Real' example tested on "MSVC2005 Express".
- Don't use 'debug watch' of VC. Sometimes it show wrong information!.
(Note: C++ standard doens't define anything about the way of implementing dynamic polymorphism. So, results are dependent on compiler.)

==================================
Non-Virtual Inheritance
class Animal
{
  virtual void Eat(){};
  int animal;
};

Animal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Mammal : public Animal
{
  virtual void Run(){};
  int mammal
};

Mammal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+     Mammal::Run()
  |   int animal    |
  +-----------------+
  |   int mammal    |
  +-----------------+

class Winged : public Animal
{
  virtual void Flap(){};
  int winged
};

Winged
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+     Winged::Flap()
  |   int animal    |
  +-----------------+
  |   int winged    |
  +-----------------+

class Bat : public Mammal, public Winged
{
  virtual void Hang(){};
};

Bat
  +-----------------+
  |   __vfptr       |---> Animal::Eat() (*1) [from Mammal]
  +-----------------+     Mammal::Run()
  |   int animal    |     Bat::Hang()
  +-----------------+
  |   int mammal    |
  +-----------------+
  |   __vfptr       |---> Animal::Eat() (*2) [from Winged]
  +-----------------+     Winged::Flap()
  |   int animal    |
  +-----------------+
  |   int winged    |
  +-----------------+

(Address of (*1) and (*2) is different.)

======================================
Virtual Inheritance

class Animal
{
public:
  Animal():animal(){}
  virtual void Eat(){};
  int animal;
};

Animal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Mammal : public virtual Animal
{
public:
  Mammal():mammal(){}
  virtual void Run(){};
  int mammal;
};

Mammal
  +-----------------+
  |   __vfptr       |---> Mammal::Run()
  +-----------------+
  |   ???????????   |
  +-----------------+
  |   int mammal    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Winged : public virtual Animal
{
public:
  Winged():winged(){}
  virtual void Flap(){};
  int winged;
};

Winged
  +-----------------+
  |   __vfptr       |---> Winged::Flap()
  +-----------------+
  |   ???????????   |
  +-----------------+
  |   int winged    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Bat : public Mammal, public Winged
{
  virtual void Hang(){};
};

Bat
  +-----------------+
  |   __vfptr       |---> Mammal::Run()
  +-----------------+     Bat::Hang()
  |   ??????????    |
  +-----------------+
  |   int mammal    |
  +-----------------+
  |   __vfptr       |---> Winged::Flap()
  +-----------------+
  |   ??????????    |
  +-----------------+
  |   int winged    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+
===============================

NOTE: I have no idea what "?????" means. I think this is only for internal use of VC.

Here is view of this.

"---." : reference member (p.xxx)
"--->" : pointer member (p->xxx)

Non-virtual inheritance
  bat
  |----. Mammal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415770) --- (*1)
  | | | |----> Animal::eat(void)
  | | | |----> Mammal::setHairColor(void)
  |
  |----. WingedAnimal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415760) --- (*2)
  | | | |----> Animal::eat(void)
  | | | |----> WingedAnimal::flap(void)

Virtual inheritance case
  bat
  |----. Mammal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415788) --- (*3)
  | | | |----> Animal::eat(void)
  | |----. __vfptr
  | | |----> Mammal::setHairColor(void)
  |
  |----. WingedAnimal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415788) --- (*4)
  | | | |----> Animal::eat(void)
  | |----. __vfptr
  | | |----> WingedAnimal::flap(void)

We should focus on that pointed address indicated at (*1) and (*2) is different, but the one at (*3) and (*4) is same - actually, it's not separated entity, it's same one. That is, there is one vftable for Animal class.

Now we can know the way of virtual inheritance.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

See following example codes.

class A
{
public:
    virtual int a(void) {return 1; }
    virtual int b(void) {return 11;}
    int         c(void) {return 21;}
};

class B
{
public:
    virtual int a(void) {return 2; }
    virtual int b(void) {return 12;}
    int         c(void) {return 22;}
};

class C : public A, public B
{
public:
    virtual int a(void) { return 3; }
};

void main(void)
{
    C c;
    A* pa = &c;
    B* pb = &c;
    printf("%d / %d / %d\n", pa->a(), pb->a(), c.a()); // OK ---(*1)
    printf("%d\n", c.b());  // Compile Error due to ambiguous access ---(*2)
    printf("%d\n", c.c());  // Compile Error due to ambiguous access ---(*3)
}

In case of (*2) and (*3), Compiler gives 'Error' due to ambiguity - A::b()/B::b(). It's clear.
But, there is no ambiguity in case (*1). Function 'a' is declared as 'virtual' in A and B. And 'a' also overridden in C. So, all three parameters of 'printf' means 'C::a()'.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

".init_array" Section ".fini_array"
.init_array contains pointers to blocks of code that need to be executed when an application is being initialized (before main() is called). It is used for a number of things, but the primary use is in C++ for running static constructors; a secondary use that is sometimes used is to initialize IO systems in the C library.
If you are not using C++ you may (depending on your C library) be able to live without it entirely; but you'd need to hack your startup code to deal with this.
.init_array probably ends up in ram because its marked read/write -- that happens because in a dynamic linking environment the dynamic linker has to fix up all the pointers it contains before it can be used. In a static environment you might be able to get away with forcing it into a read-only section. 
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

From ( "Code Complete", McConnell )
  - Program organization
  - Change strategy
  - Buy-vs.-build decisions
  - Major data structures
  - Key algorithms
  - Major objects
  - Generic functionality
  - User interface.
  - input/output
  - Memory management
  - String storage (optional)
  - Error processing
  - Over-enginerring
  - Assertions
  - Fault tolerance
  - Performance

+ Recent posts