$bash

C/C++ int main, void main

0x0300 : Study/0x0304 : Programming

보통 C에서 int main으로 선언되고 void main 같은 경우에는 잘못 된 표기라 말해주는데

이 이유가 햇갈린다... 암튼 잘못된 선언인데 그 이유를 알아보자.


1
2
3
int main(){
    return 0;
}
cs


보통의 main 선언문 이다. 마지막에 대부분 return 0; 를 선언 해주는데 이 역할은 main() 이 정상적 으로 종료 됨을 의미하는 exit(0) 를 호출한 후, 함수를 종료하게 되는 부분이다. 이는 gcc 로 컴파일 해서 gdb나 이것저것 컴파일을 해보면 볼 수 있는데. sp(stack pointer 맞나?) 에서 main 부분 마지막 줄인 ret을 하면 libc_start_main..(정확히 이름이 기억이 나진 않넹..) 으로 점프하고 exit를 호출 하게 되는것을 확인 할 수 있다.


이때 여기서 exit()의 파라미터인 status 값은 컴파일러 마다 약간 다르게 설정되 있는데 일반적으로 0면 정상종료를 의미한다. 숫자의 의미는 각각의 에러 타입을 의미한다. 


int main()으로 하지 않고 void main() 으로 한다면 컴파일러가 컴파일 에러를 발생시키지 않아도 프로세스 상에서는 종료조건을 지정해 주지 않았기 때문에 main()함수에서 올바르지 않은 종료조건을 운영체제에 리턴하고 자신을 종료할 가능성이 있게 되어 오류가 생길 수도 있게 된다.

'0x0300 : Study > 0x0304 : Programming' 카테고리의 다른 글

C/C++ calloc vs malloc+memset  (0) 2017.10.20
C/C++ 제곱근 SQRT  (0) 2017.10.19
C/C++ string in switch/case  (0) 2017.10.18
python z3  (0) 2017.07.24
python subprocess  (0) 2017.07.10

C/C++ string in switch/case

0x0300 : Study/0x0304 : Programming

요새 CTF를 하면서 C든 뭐든 프로그래밍 너무 못한다 생각이 너무나도 들어서 다시 공부하고 있다.

그때마다 생각나는거 생각을 써야겠다.


1
2
3
4
5
6
7
8
9
10
switch(string)
{
case "Name":
...
break;
case "Age":
...
break;
}
 
cs


위 구문은 switch 문을 그냥 의식의 흐름(?) 대로 string을 해봤는데...

switch의 controlling expression을 정수 형 대신 문자열를 사용 할 수 없기에 위 구문은 당연히 될 수가 없다.


switch 명령은 case가 많을수록 이론상으로 if문과 성능 차이가 기하급수로 벌어지게 되어 있다. 왜 그럴까?

if - else if 열거식의 경우엔 비교하는 대상 중 어느 한쪽이 상수라면 자동으로 점핑 테이블을 만들어 마치 switch - case처럼 동작하기 때문이다. 좀 더 자세히 생각해 보면, 상수 값에 따라 IP(Instruction Pointer) 는 함수호출처럼 자신의 주소를 향해 뛰어간다. break 구문을 만나면 switch 가 끝나는 블럭으로 또 한 번 점프한다. break 나 continue 는 goto 구문의 다른 (특수한 용도로 한정된) 이름이다. 그런데 상수가 아닐 경우는 점핑 테이블 생성이 불가능해진다. 결과적으로 속도에서 차이가 날 수 밖에 없다는 것이다. jmp table을 쓰는 것은 시간이 오래 걸리는 테이블 생성 작업을 1회 한 후 한 번의 비교로 원하는 곳으로 찾아가 작업하겠다는 성능을 기대하는 것인데 변수가 case에 들어가게 되면 일반적인 if - else if 로밖에 구현이 안되는 것이다.


EIP = EIP + jmptable[Index]; 

// 이게 맞는건지는 나도 잘 모르겠따리...


많은 case를 string을 넣어 사용한다면 결론적으로 많은 jmp table 요구한다. 게다가 변수가 상수가 아닐 경우에는 Index 값 자체가 산출되지 않아 저런 식으로는 불가능하고 연결리스트 따위를 동원해야하니 속도 성능 같은 건 기대도 못 할지도 모른다.


1
2
3
4
5
6
7
if(strcmp(string"Name"== 0)
{
}
else if(strcmp(string"Age"== 0)
{
}
else ...
cs


if를 써서 strcmp 를 사용하여 위의 switch 구문을 표현 할 수 있다. 사실 그냥 내가 case 써서 string으로 구현하고 싶은 맘이다.

사실2 더 큰 문제는 else if 중첩에는 한계가 있다는 것이다. (error code C106 참고)


C++ 로 먼저 좀 생각해보자. jmptable 을 요구하여 한다면, STL 를 사용하여 테이블을 생성하여 점프를 한다면 충분히 가능하지 않을까 생각이 든다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static map< stringint > m;
void Init(){
    m["Name"= ENUM_NAME;
    m["Age"= ENUM_AGE;
}
 
void func(){
    switch(m[string]){
        case ENUM_NAME:
            ...
            break;
        case ENUM_AGE:
            ...
            break;
        }
}
cs


map를 사용하여 switch 구문에 대한 문자열 문제는 해결된다. 어느정도 많은 case 문이 나와도 깔끔하게 정리가 될 수 있고, map가 어느정도 성능을 개선 해 주기 때문에 좋다고 생각한다. 하지만 정말로 괜찮을까?


초기화 함수 하나 만들고 변수 하나 선언하고 열거형을 만들면 된다. 하지만 이런 작업을 하고 있으면 굉장한 손해를 본다. 성능상으로야 가장 좋지만(map 대신 hash_map을 쓴다면, 비록 표준은 아니지만 성능으로는 좋은 성과를 볼 수 있다.) 코드의 유지보수 관리에는 그켬을 초래할 수 있다.


머 중요한 사실은 cpp을 하는 것은 아니고 내가...이러한 문제는 따로 STL map에 따로 case token 을 선언해준다면 충분히 해결 될 것이라고 생각한다.


어디까지나 cpp 조빱이 생각한거라... 나도 올바른 정답은 아니다. 또 원래 C를 공부 하고 있어서 C에 대해서도 찾아봤다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define BADKEY -1
#define A1 1
#define A2 2
#define B1 3
#define B2 4
 
typedef struct { char *key; int val; } t_symstruct;
 
static t_symstruct lookuptable[] = {
    { "A1", A1 }, { "A2", A2 }, { "B1", B1 }, { "B2", B2 }
};
 
#define NKEYS (sizeof(lookuptable)/sizeof(t_symstruct))
 
int keyfromstring(char *key)
{
    int i;
    for (i=0; i < NKEYS; i++) {
        t_symstruct *sym = lookuptable + i*sizeof(t_symstruct);
        if (strcmp(sym->key, key) == 0)
            return sym->val;
    }
    return BADKEY;
}
 
/* ... */
switch (keyfromstring(somestring)) {
case A1: /* ... */ break;
case A2: /* ... */ break;
case B1: /* ... */ break;
case B2: /* ... */ break;
case BADKEY: /* handle failed lookup */
}
cs


stack overflow에서 나온 자료인데...그냥 if 쓰는게 더 나을꺼 같따...

위 소스에 대해서는 해당 링크를 참고 하면된다.


링크 :: https://stackoverflow.com/questions/4014827/best-way-to-switch-on-a-string-in-c

'0x0300 : Study > 0x0304 : Programming' 카테고리의 다른 글

C/C++ 제곱근 SQRT  (0) 2017.10.19
C/C++ int main, void main  (0) 2017.10.18
python z3  (0) 2017.07.24
python subprocess  (0) 2017.07.10
python json  (0) 2017.07.10

How to Create a Programming Language

0x0300 : Study/0x0306 : ETC

How to Create a Programming Language?


1. Become familiar with terminology.

Compiler writers often use unfamiliar terminology. Read up on compilers before proceeding. Be sure to know everything that you need to know.


2. Decide what problem your language is solving.

Is it addressing a domain-specific problem, or is it a general purpose language?


3. Think about the semantics of your language and the concepts of it.

- Are you going to allow direct pointer access or not?

- What are the data types of your language?

- Is it a static or dynamic language?

- What is your memory model? Are you going to use a garbage collector or manual memory management? (If you use a garbage collector, prepare to write one or adapt an existing one to your language.)

- How are going to handle concurrency? Are you going to use a simple threading/locking model or something more complex like - Linda or the actor model? (Since nowadays computers have multiple cores.)

- Are there primitive functions embedded in the language or will everything come from a library?

- What is the paradigm or paradigms of you language? Functional? Object-oriented? Prototype (like JavaScript)? Aspect-oriented? - Template oriented? Or something entirely new?

- How is your language going to interface with existing libraries and languages (mainly C)? This point is important if you're building a domain-specific language.

- Finally, some of the answers to this questions are going to be answered by the second step and will help you answer the next step.


4. Think of some specific tasks that someone would want to be able to perform with your language.

For example, 'they may want to direct a robot to follow a line' or 'they may want to create relatively portable desktop programs in it' or 'they may want to create web applications with it'.


5. Experiment with syntax ideas (the text of the language) for the above examples.

Be careful to keep your language in the context-free language category or something inside it. Your parser generator and you will appreciate it later on.


6. Write out a formal grammar for the syntax.


7. Decide whether the language will be interpreted or compiled.

Meaning that in the interpreted world your user will typically edit your program in an editor, and run it directly on the interpreter; while in the compile world, your user will edit your program, compile it, save the resulting executable somewhere and run it.


8. Write the front end scanner and parser or find a tool that helps you with this.

Also, think about how your compiler/interpreter will warn your user about erroneous programs and syntax errors.


9. Use the parser information to write the object code or an intermediate representation.

Have the parser create an AST, then create your object code from the AST using three address code or its big brother SSA, then create a symbol table to define your functions, global variables, etc.


10. Write the executor or code generator that will bind everything together.


11. Write many test programs to test the language.

You want to create programs that stress the burdens of your formal grammar in order to see that your compiler accepts everything that is inside your definition and rejects everything that is outside of it.


12. Consider how the user will debug their own programs.


13. If your language uses a standard library, you will want to write it.

Specifically, if you write a compiler, you will need the code that the operating system will execute in order to begin running the user code (for example, allocating all global variables).


14. Publish your language, along with the specification for it and some examples of what you can do in it.

Don't forget to document how you can integrate with existing libraries, languages and how to use the runtime features and/or standard library.


'0x0300 : Study > 0x0306 : ETC' 카테고리의 다른 글

Forensic ?  (0) 2017.05.21
RSA script  (0) 2017.05.08
Openssl install  (0) 2017.02.25
여기는 왜 안되는거죠....???  (0) 2016.09.08
8. 저작 재산권  (1) 2016.07.03