1. [C#] 가비지 컬렉션(Garbage Collection)

개요)
C#은 CLR(Common Language Runtime)에 의해 코드가 실행되고 관리된다.
CLR에서 가비지 컬렉터(Garbage Collector)는 자동 메모리 관리자 역할을 한다. 애플리케이션에서 메모리 할당 및 해제를 자동으로 관리한다.

장점)
개발자가 수동으로 메모리를 관리할 일이 줄어든다. -> 개발 능률 Up
관리되는 힙(managed heap)에 메모리 할당이 효율적으로 이루어진다.
객체가 다른 객체에 할당된 메모리 자체에 사용할 수 없도록 하여 메모리 보안을 제공한다.

메모리 할당)
사용자에 의해 새 프로세스가 시작되면 런타임에서는 메모리에 인접한 주소 공간 영역을 예약한다.
이 예약된 주소 공간을 관리되는 힙(managed heap)이라고 한다.
관리되는 힙에서는 객체가 할당될 주소의 포인터를 관리한다.
모든 참조 형식(reference type)은 관리되는 힙에 할당된다.

과정)
애플리케이션에서 참조 형식을 처음 만드는 경우, 이 참조 형식에 대한 메모리는 관리되는 힙의 기본 주소로 할당된다.
애플리케이션이 다음 개체를 만들 때 런타음은 처음 만든 객체 바로 다음 주소 공간에 메모리를 할당한다.
이러한 방식을 반복하여 새 객체에 대한 메모리 공간을 계속 할당한다.
관리되는 힙은 관리되지 않는 힙(unmanaged heap)에서 할당하는 것보다 속도가 더 빠르다.
런타임에서 포인터에 값을 더하여 객체의 메모리를 할당하기 때문에, 스택에서 메모리를 할당하는 속도만큼 빠르다.
또한, 연속으로 할당된 새 객체는 인접한 주소를 통해 빠른 속도로 액세스할 수 있다.

메모리 해제)
가비지 컬렉터의 최적화 엔진은 수행 중인 할당에 따라 수집을 수행하기에 가장 적합한 시간을 결정한다.
애플리케이션에서 더 이상 사용되지 않는 객체에 대한 메모리를 해제한다.
애플리케이션의 루트를 검사하여 더 이상 사용되지 않는 개체를 결정한다.
애플리케이션 루트에는 다음이 포함된다.

정적 필드(static field)
스택 객체
CPU 레지스터 등

GC는 이 목록을 사용하여 루트를 통해 연결할 수 있는 모든 객체 그래프를 생성한다.
그래프에 연결되지 못한 객체는 가비지 컬렉터에서 가비지로 간주하고 할당을 해제한다.

가비지 컬렉션)
가비지 컬렉션은 다음 조건 중 하나가 충족될 경우 발생한다.
시스템 메모리 부족
관리되는 힙의 할당된 객체에 사용되는 메모리가 허용되는 최대치를 초과
GC.Collect 메서드 호출

세대)
관리되는 힙은 세대별로 나눠져 관리된다. 주로 0세대, 1세대, 2세대로 나뉜다.

0세대
새로 할당된 객체의 메모리 영역으로, 주로 이 세대에서 가비지 컬렉션이 자주 발생한다.
대부분의 객체는 0세대에서 정리되며 다음 세대까지 남아있지 않는다.
0세대가 가득 찼을 때 새 객체가 할당될 경우, 먼저 0세대 영역에서 검사가 이루어진다.

1세대
0세대 컬렉션을 수행한 후 살아남은 메모리를 압축하여 1세대로 승격한다.
컬렉션이 0세대에서 충분한 공간을 확보하지 못한 경우, 1세대와 2세대에서 수행한다.

2세대
가장 오랫동안 살아남은 객체들이 저장되는 공간이다.
대량 객체 힙(3세대)의 객체는 2세대에서도 컬렉션이 이루어진다.
관리되지 않는 리소스
대부분의 객체는 자동으로 관리되지만, 명시적인 정리가 필요한 관리되지 않는 리소스가 존재한다.

Dispose
이런 경우 IDisposable 인터페이스를 통해 Dispose 메서드를 재정의 하여 관련 작업을 수행한다.
public class MyClass : IDisposable
{
public void Dispose
    {
     //정리 로직 구현
    }
}
객체 사용을 마치면, 명시적으로 Dispose 메서드를 호출해야 한다.
Finalize
만일, 실수로 Dispose를 호출하지 않았을 경우를 대비하여 정리하는 방안도 마련할 수 있다.
객체가 가비지 컬렉션 될때 호출되는 Finalize를 재정의를 통해 수행하게 된다.
public class MyClass : IDisposable
{
public void Dispose {...}
    
    ~MyClass()
    {
     //정리 로직 구현
    }
}
다만 가비지 컬렉션 도중 특정 객체의 다른 작업이 수반되는 것이므로 성능 이슈가 발생한다.
이 방식은 되도록 사용하지 않는 것이 좋다.


1. 메모리 구조(C)

스택영역
우리는 이제껏 스택영역에 메모리를 할당해 왔습니다. 컴파일 시점에 결정되는 영역입니다.

힙 영역
이 영역의 메모리는 실행시점(Run Time)에 결정됩니다. 프로그래머에 의해서요. 이 영역을 힙영역이라고 합니다.

데이터 영역
이 영역의 메모리는 정적변수, 전역변수, 구조체 등 함수 외부에서 선언되는 변수들이 이 메모리에 할당됩니다.

코드 영역
코드영역에는 프로그램의 실행 명령어들이 존재합니다.

우리가 이번에 주목해야할 영역은 힙영역입니다. 위의 코드를 정상적이게 동작시키기 위해서는요.
그 목적을 달성하기 위해서 나온 함수가 바로 malloc함수입니다. malloc함수는 stdlib헤더에 선언되어 있으며 malloc함수를 사용하기 위해서는 stdlib.h를 include해야합니다.

void *malloc(size_t size)

이 함수는 size만큼의 메모리를 힙영역에 할당합니다. 어떤 자료형일지 모르니 반환형 데이터는 void포인터입니다. 
하지만 그냥 메모리만 할당하고 해제하지 않으면 메모리가 누출됩니다. 우리는 메모리를 이제 쓰지 않을 경우(거의 함수 반환 직전)에 free함수를 써서 메모리를 해제해야합니다.

void free(void *ptr)

#함수를 하나만 사용해서, 두개의 함수를 구현하는 방법(오버라이딩의 진화,ㅡ,ㅡㅡ)
#함수를 하나만 사용해서, 두개의 함수를 구현하는 방법(오버라이딩의 진화,ㅡ,ㅡㅡ)
#함수를 하나만 사용해서, 두개의 함수를 구현하는 방법(오버라이딩의 진화,ㅡ,ㅡㅡ)


using System;

class Program
{
    public static void Main(string[] args)
    {
        checkparameters nm = new checkparameters();
nm.run();

checkparametersdown nmm = new checkparametersdown();
nmm.run();
    }
}

//함수를 하나만 사용해서, 두개의 함수를 구현하는 방법
//함수를 하나만 사용해서, 두개의 함수를 구현하는 방법
class checkparameters
{
    void basefrm(string portno, string apmLiteRedismanager, string apmLiteRedismanagers = null )
    {
        Console.WriteLine(portno + "/" + apmLiteRedismanager + "/" + apmLiteRedismanagers);
    }
    public void run()
    {
        basefrm("1010", "1010");
basefrm("1010", "1010", "1010");
    }
}
class checkparametersdown
{
    void basefrm(string portno, string apmLiteRedismanager, string apmLiteRedismanagers)
    {
        Console.WriteLine(portno + "/" + apmLiteRedismanager + "/" + apmLiteRedismanagers);
    }
    void basefrm(string portno, string apmLiteRedismanager)
    {
        Console.WriteLine(portno + "/" + apmLiteRedismanager);
    }
    public void run()
    {
        basefrm("1010", "1010");
basefrm("1010", "1010", "1010");
    }
}



[Git] push 명령어로 local 변경 사항 원격 저장소에 반영하기
[Git] push 명령어로 local 변경 사항 원격 저장소에 반영하기
[Git] push 명령어로 local 변경 사항 원격 저장소에 반영하기
[Git] push 명령어로 local 변경 사항 원격 저장소에 반영하기
[Git] push 명령어로 local 변경 사항 원격 저장소에 반영하기







아래는 해당 프로젝트 소스디렉토리로 이동해서 수정된 부분을 반영하는 방법이다.

>cd ~/source/repository/Final/
>git branch -M BRANCH_PROJECT_NAME
>git add .
>git commit -m "query 2024.01.25 history commit"
>git push -u origin BRANCH_PROJECT_NAME


- git commit과 push의 차이점 이해하기
- git commit과 push의 차이점 이해하기
- git commit과 push의 차이점 이해하기

그렇다면 git commit과 push의 차이는 뭘까?
그렇다면 git commit과 push의 차이는 뭘까?
그렇다면 git commit과 push의 차이는 뭘까?

git commit만으로는 왜 원격 저장소에 반영이 안될까?
git commit만으로는 왜 원격 저장소에 반영이 안될까?
git commit만으로는 왜 원격 저장소에 반영이 안될까?

우리가 데이터를 변경한 후 commit을 하면 그 내역은 로컬 저장소에 반영이 된다.
우리가 데이터를 변경한 후 commit을 하면 그 내역은 로컬 저장소에 반영이 된다.
우리가 데이터를 변경한 후 commit을 하면 그 내역은 로컬 저장소에 반영이 된다.
즉, 내 pc 내의 저장소에만 반영이 된 것이다.
즉, 내 pc 내의 저장소에만 반영이 된 것이다.
즉, 내 pc 내의 저장소에만 반영이 된 것이다.

로컬저장소에 반영된 변경 사항을 원격에도 반영하기 위한 도구가 push다.
로컬저장소에 반영된 변경 사항을 원격에도 반영하기 위한 도구가 push다.
로컬저장소에 반영된 변경 사항을 원격에도 반영하기 위한 도구가 push다.

commit한 내역을 push하게 되면, 이제 원격 저장소에도 그 내역이 업데이트 되는 것이다.
commit한 내역을 push하게 되면, 이제 원격 저장소에도 그 내역이 업데이트 되는 것이다.
commit한 내역을 push하게 되면, 이제 원격 저장소에도 그 내역이 업데이트 되는 것이다.

따라서, commit은 내 pc 내의 작업이 때문에 크게 위험하지 않다.
따라서, commit은 내 pc 내의 작업이 때문에 크게 위험하지 않다.
따라서, commit은 내 pc 내의 작업이 때문에 크게 위험하지 않다.

하지만 push는 원격 저장소, 즉 공동으로 작업하는 프로젝트에 (개인 프로젝트일 수도 있지만)
하지만 push는 원격 저장소, 즉 공동으로 작업하는 프로젝트에 (개인 프로젝트일 수도 있지만)
하지만 push는 원격 저장소, 즉 공동으로 작업하는 프로젝트에 (개인 프로젝트일 수도 있지만)

그 내역이 반영되는 것이기 때문에 신중하게 해야한다.
그 내역이 반영되는 것이기 때문에 신중하게 해야한다.
그 내역이 반영되는 것이기 때문에 신중하게 해야한다.





 

"파일"이라는 한글을 여러타입으로 저장후에 c언어에서 읽어서 출력해보기
"파일"이라는 한글을 여러타입으로 저장후에 c언어에서 읽어서 출력해보기
"파일"이라는 한글을 여러타입으로 저장후에 c언어에서 읽어서 출력해보기


c언어에서 언어셋을 다루는일은 어려운일이다. 특히 한글을 다루는 일은 더더욱 그렇다.
아래는 여러가지 방식으로 저장되어진 "파일"이라는 한글을 바이트단위로 출력해본다.

 

 

#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    int kk;
    char tmp[1024];
    FILE *fp = NULL;

    if(argc != 2) return(-1);

    if(( fp = fopen(argv[1], "rt")) == NULL) return(-1);

    memset(tmp, 0x00, sizeof(tmp));

    while(1)
    {
        memset(tmp, 0x00, sizeof(tmp));
        if(fgets(tmp, sizeof(tmp), fp) == NULL) break;

        for(kk=0; kk<sizeof(tmp); kk++)
        {
            if(tmp[kk]==0x00) break;
            printf("[%d],", tmp[kk]);
        }
        printf("\n");
        printf("%s", tmp);
        printf("\n");
    }

    if(fp != NULL) fclose(fp);
    return(0);
}

# Windows Console에 Sin,Cos 그래프 표시

 

 

 



using System;

class Program
{
    public static void Main(string[] args)
    {
        CHKNM nmm = new CHKNM();
nmm.RUN();
    }
}
class CHKNM
{
    //Console Width, Heigth
    int width = 0;
    int height = 0;

    //Math.Cos,Math.Sin's Value to mapping Console Screen Size
    double mapx = 0.0;
    double mapy = 0.0;

    int toggle = 0;
    int nextxpos = 0;

    int end_degree_value = 360 * 2;

    public void RUN()
    {
width  = Console.WindowWidth;
        height = Console.WindowHeight;

        //Dynamic array index possible
int[,] screenposition = new int[width,height];

for(int ii=0; ii<height; ii++)
for(int kk=0; kk<width; kk++)
{
    screenposition[kk,ii]=0;
}

        for(int degree = 1; degree < end_degree_value; degree++)
{
    double radian = Math.PI * degree / 180.0;
    double funcy = Math.Cos(radian) + 1.0;

    mapy = height * 0.99 / 4.0;
    mapx = Convert.ToDouble(width) / Convert.ToDouble(end_degree_value);

    int ypos = Convert.ToInt32(funcy * mapy);
    int xpos = Convert.ToInt32(degree * mapx);

    if(ypos == height) continue;
    if(xpos == width) continue;

            if(toggle == 0)
    {
        toggle = 100;
nextxpos = xpos;
screenposition[xpos,ypos]=1;
    }
    else
    {
        if(nextxpos == xpos) continue;
else
{
    screenposition[xpos,ypos]=1;
    nextxpos = xpos;
}
    }
}
#if(true)
        string screenTxt = "";
for(int ii=0; ii<height/2; ii++)
{
    for(int kk=0; kk<width; kk++)
    {
        if(screenposition[kk,ii] == 1) screenTxt += "*";
else screenTxt += " ";
    }
    screenTxt += "\n";
}
Console.WriteLine(screenTxt);
#endif
    }
}









 

 

 

현재 로칼 컴퓨터의 아이피 알아내기





using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Diagnostics;
using System;
using System.Linq;
using System.Net;

class Program
{
    public static void Main(string[] args)
    {
        NETNM nmm = new NETNM();
        nmm.RUN();
    }
}
class NETNM
{
    public void RUN()
    {
        var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                Console.WriteLine(ip.ToString());
            }
        }
    }
}

문제

'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다.

게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. 보드의 상하좌우 끝에 벽이 있다. 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. 뱀은 처음에 오른쪽을 향한다.

뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.

  • 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.
  • 만약 벽이나 자기자신의 몸과 부딪히면 게임이 끝난다.
  • 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다.
  • 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워준다. 즉, 몸길이는 변하지 않는다.

사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산하라.

입력

첫째 줄에 보드의 크기 N이 주어진다. (2 ≤ N ≤ 100) 다음 줄에 사과의 개수 K가 주어진다. (0 ≤ K ≤ 100)

다음 K개의 줄에는 사과의 위치가 주어지는데, 첫 번째 정수는 행, 두 번째 정수는 열 위치를 의미한다. 사과의 위치는 모두 다르며, 맨 위 맨 좌측 (1행 1열) 에는 사과가 없다.

다음 줄에는 뱀의 방향 변환 횟수 L 이 주어진다. (1 ≤ L ≤ 100)

다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지는데, 정수 X와 문자 C로 이루어져 있으며. 게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다. X는 10,000 이하의 양의 정수이며, 방향 전환 정보는 X가 증가하는 순으로 주어진다.

출력

첫째 줄에 게임이 몇 초에 끝나는지 출력한다.

+ Recent posts