<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>HR</title>
    <link>https://hr-crypto.tistory.com/</link>
    <description>주니어 개발자</description>
    <language>ko</language>
    <pubDate>Fri, 17 Apr 2026 01:52:58 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>HHRR</managingEditor>
    <image>
      <title>HR</title>
      <url>https://tistory1.daumcdn.net/tistory/5170234/attach/d8e06883d66b4f108a5af27c0b65fb0f</url>
      <link>https://hr-crypto.tistory.com</link>
    </image>
    <item>
      <title>[Oralce] 락 쿼리 (Lock Query), 실행 흐름</title>
      <link>https://hr-crypto.tistory.com/63</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;락 쿼리(Lock Query) 란?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스에서 특정 데이터를 수정하거나 삭제하기 전에 미리 Lock을 걸어, 다른 트랜잭션이 동시에 해당 데이터를 변경하지 못하도록 제어하는 쿼리.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;왜 락 쿼리가 필요한가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 동시 업데이트 충돌&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A트랜잭션, B트랜잭션이 동시에 같은 데이터를 w 하려고 하고, B가 마지막에 끝난 트랜잭션이라고 가정해보자. 그러면 마지막에 B 트랜잭션이 수정한 값만 DB에 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. r-w 충돌&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A트랜잭션이 수정 중인 데이터를 B 트랜잭션이 동시에 읽게되면 시점에 따라 수정 전의 값을 조회하게됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, 입금 처리하는 트랜잭션이라고 가정을 해보자. A는 +50원, B는 +30원 을 처리하는 트랜잭션이고 사용자의 잔고에는 100원이 있다고 하자. A와 B가 동시에 트랜잭션 처리를 하려고 들어오게되면, 잔고는 180원이 아닌 130&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(B가 제일 마지막 처리)으로 잘못 반영된다 &lt;/span&gt;Race Condition 경쟁상태 에 빠지게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;=&amp;gt; 이를 막기 위해 락쿼리를 적용해서 트랜잭션 간 충돌을 방지하고, 일관된 데이터 처리를 해야한다. 따라서 입금 전 잔액을 조회하면서 해당 행에 락을 걸고, 다른 트랜잭션이 접근하지 못하도록 해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;락 쿼리 종류&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;1. `&lt;/span&gt;SELECT ... FOR UPDATE`&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 행을 수정하기 전, 해당 행에 대한 락을 걸고 다른 트랜잭션의 접근을 차단&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1749985847373&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- ① 해당 계좌 조회하면서 락 걸기
SELECT balance
FROM accounts
WHERE account_no = '123-456-7890'
FOR UPDATE;

-- ② 입금 처리 (예: 5만원 입금)
UPDATE accounts
SET balance = balance + 50000
WHERE account_no = '123-456-7890';

-- ③ 트랜잭션 종료 &amp;rarr; 락 해제
COMMIT;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;=&amp;gt; 입금 처리 중 다른 트랜잭션이 동일 계좌에 접근하지 못함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;FOR UPDATE&lt;/span&gt; : 트랜잭션 종료되어서 락 해제시까지 무한 대기&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;FOR UPDATE NOWAIT&lt;/span&gt; : 바로 에러 뱉어서 즉시 빠져나옴&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+) 테이블 전체가 아닌 행 단위 락이다. 특정 행만 락이 걸리는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;2. `LOCK TABLE ... IN [MODE]`&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테이블 전체에 락을 거는 명령 (예: SHARE MODE, EXCLUSIVE MODE 등)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;세션 A가 락을 걸었을떄 B가 그냥 조회, 락 조회, 업데이트 세가지 행동을 했을때 어떤 흐름인지 궁금해졌다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;세션 A&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1759997958109&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * 
FROM accounts 
WHERE account_no = '123-456-7890'
FOR UPDATE NO WAIT;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오라클은 이 시점에 account_no = '123-456-7890' 행에 배타적 락을 걸어두므로, 세션 A만 이 행을 수정할 수 있음.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;따라서 A가 해당 행에 락을 걸어두고 update 치면 바로 갱신 가능.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;세션 B&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1759998362592&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- 단순 조회 
SELECT *
FROM accounts
WHERE account_no = '123-456-7890';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 B가 동시에 동일 계좌 조회를 시도하면 -&amp;gt; 그냥 읽기 가능&lt;/p&gt;
&lt;pre id=&quot;code_1759998007356&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- 락 조회
SELECT * 
FROM accounts 
WHERE account_no = '123-456-7890'
FOR UPDATE NOWAIT;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 락쿼리로 조회했다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A가 해당 행을 락 중이므로, B 는 NOWAIT로 접근 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;=&amp;gt; 업데이트 치기 전 조회하는 쿼리에는 락을 걸어서 조회에서 no wait으로 튕기게하고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;일반 조회하는 쿼리는 락과 상관없이 조회가 가능하도록 설계 해야겠다&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1759998026991&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * 
FROM accounts 
WHERE account_no = '555-666-7777'
FOR UPDATE NOWAIT;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 B가 같은 테이블 다른 행에 대해 락 조회할때는 당연히 정상 실행됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;그러면 내가 궁금한건, A가 락을 잡은 상태에서 B가 일반 조회 후에 update를 시도한다면?&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1759998958154&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;UPDATE accounts 
SET amt=amt+1 
WHERE accounts_no='123-456-7890';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 락 대기 상태에 빠진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 update 시점에 락을 얻으려고 하는데, 이미 세션A가 락을 잡고있으니 B는 대기하게 되는 것.. wait 모드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상황에서 세션 B가 무한대기 상태에 빠질 수 있겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;update 전 조회 쿼리에는 lock 잡을지 말지 잘 판단해서 데이터 정합성을 지키자&lt;/p&gt;</description>
      <category>SQL</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/63</guid>
      <comments>https://hr-crypto.tistory.com/63#entry63comment</comments>
      <pubDate>Thu, 9 Oct 2025 17:39:28 +0900</pubDate>
    </item>
    <item>
      <title>[C] 포인터, 이중 포인터 구조</title>
      <link>https://hr-crypto.tistory.com/71</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해도해도 헷갈리는 포인터&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;amp; : 메모리 주소&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int a = 10;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;printf(&lt;span&gt;&quot;%p&quot;&lt;/span&gt;, &lt;b&gt;&amp;amp;a&lt;/b&gt;);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: a의 주소 0x7ffeed4cf61c&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* : 값&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int a = 10;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int *p = &amp;amp;a; // p는 a의 주소를 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;printf(&quot;%d&quot;, *p);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: *p 는 p가 가리키는 주소 안의 값 즉, 10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;int *p : 포인터 p&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1759995460526&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int a = 10;
    int *p = &amp;amp;a;

    printf(&quot;a = %d\n&quot;, a);
    printf(&quot;&amp;amp;a = %p\n&quot;, (void*)&amp;amp;a);
    printf(&quot;p  = %p\n&quot;, (void*)p);
    printf(&quot;*p = %d\n&quot;, *p);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이라면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a = 10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;amp;a = 0x7ffeed4cf61c&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p =&amp;nbsp;0x7ffeed4cf61c&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*p = 10&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1759996204178&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void swap_int(int *a, int *b) {
    int tmp = *a;  // a가 가리키는 곳의 값
    *a = *b;       // b가 가리키는 값 복사
    *b = tmp;      // tmp로 복원
}

...
int main(void) {
    /* 1) 스택 vs 힙, 기본 포인터 */
    int a = 10, b = 20;
    printf(&quot;[before swap] a=%d b=%d &amp;amp;a=%p &amp;amp;b=%p\n&quot;, a, b, (void*)&amp;amp;a, (void*)&amp;amp;b); // 10 20 0x123 0x456
    swap_int(&amp;amp;a, &amp;amp;b); // a는 b의 값, b는 a의 값
    printf(&quot;[after  swap] a=%d b=%d *&amp;amp;a=%d *&amp;amp;b=%d &amp;amp;a=%p &amp;amp;b=%p \n\n&quot;, a, b, *(&amp;amp;a), *(&amp;amp;b), (void*)&amp;amp;a, (void*)&amp;amp;b); // 20 10 20 10 0x123 0x456
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[before&amp;nbsp;swap]&amp;nbsp;a=10&amp;nbsp;b=20&amp;nbsp;&amp;amp;a=0x16b7630a4&amp;nbsp;&amp;amp;b=0x16b7630a0&lt;br /&gt;[after&amp;nbsp;&amp;nbsp;swap]&amp;nbsp;a=20&amp;nbsp;b=10&amp;nbsp;*&amp;amp;a=20&amp;nbsp;*&amp;amp;b=10&amp;nbsp;&amp;amp;a=0x16b7630a4&amp;nbsp;&amp;amp;b=0x16b7630a0&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 주소는 그대로고 값만 바뀜&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소 자체도 바꾸고싶으면 &lt;b&gt;이중포인터&lt;/b&gt; 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1759996301826&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void swap_ptr(int **p, int **q) {
    int *tmp = *p;
    *p = *q;
    *q = tmp;
}

 int x = 1, y = 2;
int *px = &amp;amp;x;
int *py = &amp;amp;y;

swap_ptr(&amp;amp;px, &amp;amp;py);  // px와 py 자체가 서로 바뀜

// 이제 px는 &amp;amp;y, py는 &amp;amp;x를 가리킴&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 &lt;b&gt;이중 포인터&lt;/b&gt; 쓸 때 힙 할당 부분 자세히 보자&lt;/p&gt;
&lt;pre id=&quot;code_1759996763592&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void set_ptr_to_heap(int **out, int value) {
    *out = (int*)malloc(sizeof(int));   // (1)
    if (!*out) { perror(&quot;malloc&quot;); exit(1); }  
    **out = value;                      // (2)
}
...
main 함수 내부

int *p = NULL;
set_ptr_to_heap(&amp;amp;p, 42);
printf(&quot;double pointer: p=%p *p=%d &amp;amp;p=%p\n&quot;, (void*)p, *p, (void*)&amp;amp;p); // (3)
free(p); // (4)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호출 전&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 : p -&amp;gt; NULL&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;set_prt_to_heap 함수 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;out == &amp;amp;p (p의 주소)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*out == p (p 변수 자체)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) malloc으로 힙에 4바이트(int 크기) 공간 잡고 주소 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙 : 0x1000 -&amp;gt; [] &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(값은 아직 없는 상태)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 : p -&amp;gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;0x1000&lt;span&gt; (p가 새 주소 가짐)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(2) **out == *(*out) == *p == p의 값&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙 : 0x1000 -&amp;gt; [42]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(**out = 42 &amp;lt;=&amp;gt; 힙 공간에 42를 넣는다)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;스택 : p -&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;0x1000&lt;span&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(3)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;p&amp;nbsp;=&amp;nbsp;0x1000&lt;br /&gt;*p&amp;nbsp;=&amp;nbsp;42&lt;br /&gt;&amp;amp;p&amp;nbsp;=&amp;nbsp;0x7ffee3a7f5a0&amp;nbsp;&amp;nbsp;&amp;nbsp;(p&amp;nbsp;변수&amp;nbsp;자체의&amp;nbsp;주소)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(4) free(p)&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;힙에 있는 0x1000 공간 해제&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙 : (빈 공간)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 : p -&amp;gt; 0x1000 (유효하지 않은 주소)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p 자체는 여전히 0x1000을 가지고 있지만 그 주소가 가리키던 메모리는 더 이상 존재하지 않음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 free 후에는 반드시 p=NULL; 로 초기화 하는 습관이 중요&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/71</guid>
      <comments>https://hr-crypto.tistory.com/71#entry71comment</comments>
      <pubDate>Thu, 9 Oct 2025 17:17:37 +0900</pubDate>
    </item>
    <item>
      <title>[C] 메모리 관리 원칙</title>
      <link>https://hr-crypto.tistory.com/70</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;메모리 관리는 누가 하느냐&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램이 실행되기 위해서는 메모리가 필요하다. RAM(주기억장치)은 프로그램이 작업을 수행하는 공간이고, 이 공간이 넉넉할 수록 컴퓨터는 더 많은 작업을 빠르게 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한정된 자원을 충돌없이 효율적으로 사용하기 위해서는 정교한 메모리 관리가 필요한데, 이 메모리 관리는 응용프로그램이 수행하지 않고 OS가 전담한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OS가 메모리를 관리하는 원칙&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 메모리 관리의 주체는 운영체제이다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응용프로그램은 메모리를 직접 제어하거나 임의의 주소에 접근 불가능하다. 대신 메모리가 필요할 경우 os 에 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우나 리눅스같은 운영체제는 &lt;b&gt;메모리 보호 기능(Segmentation, Paging, Virtual Memory 등등)&amp;nbsp;&lt;/b&gt;으로 각 프로그램 메모리 공간을 격리하고 있으며, 프로그램 간의 충돌이나 보안 침해를 방지하는 핵심 기능이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2. 운영체제는 가능한 한 메모리 요청을 수락한다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 사용 가능한 메모리가 있는 경우, 응용 프로그램이 요청한 메모리를 최대한 할당해준다. 물리적인 RAM이 부족하다면, 운영체제는 가상메모리로 부족한 메모리를 보완하려함. -&amp;gt; 얘는 속도가 느려서 성능저하 발생할수도 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 시스템에 따라 할당 요청이 거절될 수 있는데, 따라서 &lt;span style=&quot;color: #006dd7;&quot;&gt;항상 프로그래머가 메모리 요청 결과를 확인하고 예외처리를 해야한다!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;3. 한 번 할당된 메모리는 해제 전까지 보호된다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;os는 각 프로그램이 얼마만큼의 메모리를 사용하는지 관리하며, 할당된 메모리 공간을 다른 프로그램이 침범하지 않도록 보호한다. 즉, 할당된 메모리는 해당 프로그램이 명시적으로 해제할 때까지 독점적으로 사용할 수 있다. 이는 프로그램의 안정성과 신뢰성을 보장하는 중요한 원칙.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;4. 해제된 메모리는 다시 사용할 수 있다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응용프로그램이 작업을 마치고 free로 메모리를 반납하면, 운영체제는 해당 영역을 빈 공간으로 간주하고 다른 프로그램이나 이후 작업에서 재사용할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAM은 한정된 자원이므로, &lt;span style=&quot;color: #006dd7;&quot;&gt;효율적인 메모리 활용을 위해 필요한 만큼 할당하고, 다 사용한 후에는 즉시 해제하는 습관이 중요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그럼 다음으로는 c언어에서 동적 메모리 할당과 해제 방법을 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 메모리 초기화와 메모리 할당의 차이에 대해 알아보자.&lt;/span&gt;&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/70</guid>
      <comments>https://hr-crypto.tistory.com/70#entry70comment</comments>
      <pubDate>Sat, 12 Jul 2025 17:33:24 +0900</pubDate>
    </item>
    <item>
      <title>[C] 동적 메모리 할당이란? (Dynamic Memory Allocation)</title>
      <link>https://hr-crypto.tistory.com/69</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;메모리 할당&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램이 실행되기 위해서는 메모리가 필요하다. 실행 파일 자체가 메모리에 Load 되어야 실행될수 있고, 프로그램이 작업을 위해 선언하는 변수들도 모두 메모리에 할당된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int a (4byte)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;double b (8byte)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라는 변수를 사용한다고 했을 때, 컴파일러가 변수 타입에 맞는 크기만큼 메모리를 할당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;=&amp;gt; 이런식으로 프로그램 작성 시 미리 메모리 필요량을 알려주는 것이 &quot;정적 할당(Static Allocation)&quot;&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;동적 메모리 할당이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로그램 작성할 떄 (complie time or design time) 메모리 필요량을 지정하는 정적 할당과 달리, 실행중에(run time) 필요한만큼 메모리를 할당하는 기법이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동적 메모리 할당은 어느 경우에 필요할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int a[50]; 배열을 선언하면, 해당 메모리 공간이 확보될 것이다. 근데 배열 크기를 1000으로 늘리고 싶은 경우에 배열 크기를 늘리면 되지만, 메모리 필요량을 초기에 예측하기가 어렵다.. 그렇다고 너무 큰 크기로 정적 할당하는건 메모리 낭비이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 핵심은 메모리가 얼마나 필요한지 알 수 없다는 것... -&amp;gt; 이 경우에 실행중에 필요한 메모리양을 판단해서 메모리를 할당해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 프로그램 시작후에 배열 크기를 받는 방법은?&lt;/p&gt;
&lt;pre id=&quot;code_1752307354193&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int num;

printf(&quot;배열 크기를 입력해주세요&quot;);
scanf(&quot;%d&quot;, &amp;amp;num);

int a[num];

=&amp;gt; 컴파일 Error!!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote style=&quot;color: #0e0e0e;&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span&gt;int a[num];&lt;/span&gt;은 C89 컴파일러에서는 오류가 발생하지만, C99 이후부터는 Variable Length Array(VLA)를 지원하므로 허용됩니다. 다만 &lt;span&gt;&lt;b&gt;VLA는 동적 할당이 아닌 스택 메모리를 사용&lt;/b&gt;&lt;/span&gt;하기 때문에 큰 배열을 선언하면 스택 오버플로우가 발생할 수 있습니다. 그래서 일반적으로 큰 크기의 배열이나, 크기를 실행 시점에 결정해야 할 경우엔 &lt;span&gt;malloc&lt;/span&gt;과 같은 &lt;span&gt;&lt;b&gt;동적 메모리 할당&lt;/b&gt;&lt;/span&gt;이 권장됩니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 컴파일 에러가 나냐면 배열의 선언문 크기값은 변수로 지정할 수 없고, 반드시 상수로만 지정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;정적 할당 시에는 필요한 배열의 크기를 변수로 지정할 수 없다!! (&lt;/span&gt;이것이 동적 할당이 필요한 이유)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 동적 할당이 필요한 또다른 이유는 &lt;span style=&quot;color: #006dd7;&quot;&gt;임시적인 메모리가 필요할 때.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 txt 파일에 특정 문자열이 있는지만 알고 싶다고 하자. txt 파일을 검색하려면 일단 읽고, 읽기위한 버퍼가 필요하다. 이러한 버퍼를 미리 정적 할당해 놓을 필요 없이, 파일 크기만큼 동적할당 후에 원하는 작업만 하고 해제하면 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1752307607855&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char *buf = 동적할당(파일크기만큼)
buf 에 파일 읽기
(작업)
buf 해제&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파일 크기가 1M 이라고 했을 때, char buf[1048576] 과 같이 전역 버퍼를 정적할당 해놓고 작업해도 되지만, 효율이 떨어짐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 동적할당은 필요할 때 필요한만큼 메모리를 할당해 사용하고 다 쓰면 버리면 됨. (free)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;동적 할당된 메모리&lt;/b&gt;는 힙(Heap) 영역에 위치해 일단 값을 기억할 수 있지만,&lt;b&gt; 변수명이 아닌 포인터로만 접근할 수 있다.&lt;/b&gt; 그래서&lt;span&gt;malloc&lt;/span&gt;, &lt;span&gt;calloc&lt;/span&gt;, &lt;span&gt;realloc&lt;/span&gt;과 같은 함수는 힙 메모리 공간을 할당하고, 해당 영역을 가리키는 포인터를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다음으로는 메모리 관리 원칙, 동적 메모리 할당 및 해제 방법을 알아보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;출처 :&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #dddddd;&quot; href=&quot;http://www.winapi.co.kr/&quot;&gt;http://www.winapi.co.kr/&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;, Win32 Api 연구 사이트 / &lt;a style=&quot;color: #dddddd;&quot; href=&quot;https://m.blog.naver.com/cache798/130033385486&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://m.blog.naver.com/cache798/130033385486&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/69</guid>
      <comments>https://hr-crypto.tistory.com/69#entry69comment</comments>
      <pubDate>Sat, 12 Jul 2025 17:17:12 +0900</pubDate>
    </item>
    <item>
      <title>[C] 구조체 주소체계</title>
      <link>https://hr-crypto.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;구조체 포인터에 대해 알아보자.&lt;br&gt;구조체는 메모리상에 연속된 블록으로 저장되고, 그 주소가 가리키는 포인터를 선언하여 접근할 수 있다.&lt;br&gt;&amp;nbsp;&lt;br&gt;목표&lt;br&gt;1. 구조체 정의 &amp;gt;&amp;gt; 선언 &amp;gt;&amp;gt; 초기화&lt;br&gt;2. 구조체 포인터 선언 및 멤버 접근&lt;br&gt;3. 각 멤버의 메모리 주소와 값 확인&lt;br&gt;4. 구조체 메모리 레이아웃 해석&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;간단한 구조체를 선언하고 메모리 구조를 살펴보자.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;struct Person {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char name[20]; // 20bytes
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int age; // 4bytes
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float height; // 4bytes
};&lt;/code&gt;&lt;/pre&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct Person p1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct Person *ptr;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// 포인터 변수 초기화
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ptr = &amp;amp;p1;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// 구조체 멤버 값 설정
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;strcpy(p1.name, &quot;hrkim&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p1.age = 25;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p1.height = 162.5;&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;멤버 접근 방식&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;1. 직접 접근 : p1.age (일반 구조체 변수)&lt;br&gt;2. 포인터 접근 : (*ptr).age or ptr-&amp;gt;age (구조체 포인터 변수)&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;메모리 배치&lt;/h4&gt;&lt;table style=&quot;border-collapse: collapse; width: 66.2791%; height: 104px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 17px;&quot;&gt;&lt;td style=&quot;width: 18.8372%; height: 17px;&quot;&gt;멤버&lt;/td&gt;&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;주소 offset&lt;/td&gt;&lt;td style=&quot;width: 19.3024%; height: 17px;&quot;&gt;크기&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 17px;&quot;&gt;&lt;td style=&quot;width: 18.8372%; height: 17px;&quot;&gt;name&lt;/td&gt;&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;+0&lt;/td&gt;&lt;td style=&quot;width: 19.3024%; height: 17px;&quot;&gt;20 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 17px;&quot;&gt;&lt;td style=&quot;width: 18.8372%; height: 17px;&quot;&gt;age&lt;/td&gt;&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;+20&lt;/td&gt;&lt;td style=&quot;width: 19.3024%; height: 17px;&quot;&gt;4 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 17px;&quot;&gt;&lt;td style=&quot;width: 18.8372%; height: 17px;&quot;&gt;height&lt;/td&gt;&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;+24&lt;/td&gt;&lt;td style=&quot;width: 19.3024%; height: 17px;&quot;&gt;4 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 19px;&quot;&gt;&lt;td style=&quot;width: 18.8372%; height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td style=&quot;width: 28.0233%; height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;28 bytes&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(패딩 없을 경우)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;1518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHCDV2/btsOChL02nk/g5hhfwbv7DKoMrI3D5plq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHCDV2/btsOChL02nk/g5hhfwbv7DKoMrI3D5plq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHCDV2/btsOChL02nk/g5hhfwbv7DKoMrI3D5plq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHCDV2%2FbtsOChL02nk%2Fg5hhfwbv7DKoMrI3D5plq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1570&quot; height=&quot;1518&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;1518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/67</guid>
      <comments>https://hr-crypto.tistory.com/67#entry67comment</comments>
      <pubDate>Sun, 6 Jul 2025 23:42:33 +0900</pubDate>
    </item>
    <item>
      <title>[C] 예외처리, 오류처리</title>
      <link>https://hr-crypto.tistory.com/66</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 예외처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c는 예외처리를 위한 기능이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c++의 try-catch나 JAVA의 throw/catch 구문과 같은 예외처리 메커니즘을 지원하지 않는다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 어떻게 처리하냐? 함수의 반환값, 전역변수(errno), 조건검사(if문), assert 등을 이용해 오류를 처리하는 방식이 일반적이다.&lt;/p&gt;
&lt;pre id=&quot;code_1751170885887&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FILE *fp = fopen(&quot;data.txt&quot;, &quot;r&quot;);
if (fp == NULL) {
    perror(&quot;파일 열기 실패&quot;);
    exit(1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 회사도 이런식으로 오류처리를 하는데... 오류를 더 잘 처리하는 방법을 알아보자&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 나쁜 오류처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 반환값을 무시하는 경우&lt;/p&gt;
&lt;pre id=&quot;code_1751170925601&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// malloc 실패 여부를 확인하지 않음
char *buf = malloc(1024);
strcpy(buf, &quot;hello&quot;);  // buf가 NULL일 경우 crash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 의미없는 에러코드&lt;/p&gt;
&lt;pre id=&quot;code_1751170968854&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int read_data() {
    // 실패해도 -1이 아닌 0을 반환 (의미 불명확)
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) 오류 발생 위치와 원인을 숨김&lt;/p&gt;
&lt;pre id=&quot;code_1751170993967&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void foo() {
    bar();  // bar가 실패해도 foo에서 처리하지 않음
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 이거 제일 주의해야됨.... 이런식으로 처리돼서..&amp;nbsp; 오류가 어디서 났는지 로그로 확인이 어려웠던 경우가 많았다!!&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3.&amp;nbsp; 버그와 오류의 차이&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;오류(Error)&lt;/span&gt;: 실행 중 발생할 수 있는 &lt;span&gt;예측 가능한 문제&lt;/span&gt;이다. &lt;br /&gt;예: NULL 포인터, 파일 없음, 잘못된 입력 등. &amp;rarr; &lt;span&gt;프로그램이 이를 감지하고 적절히 대응해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;버그(Bug)&lt;/span&gt;: &lt;span&gt;프로그래머의 실수&lt;/span&gt;로 인해 논리적 오류나 예상치 못한 결과가 발생하는 상황이다. &lt;br /&gt;예: 잘못된 조건문, 경계값 처리 실패 등. &amp;rarr; &lt;span&gt;예외 처리로 막는 것이 아니라 코드 자체를 수정해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4.&amp;nbsp; 오류 처리 전략&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 입력 유효성은 명시하고 검사해라&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 함수가 유효한 데이터를 받는다고 가정하지 말 것&lt;/li&gt;
&lt;li&gt;필요시 함수 이름이나 주석, 문서로 유효하지 않은 입력 가능성을 명시할 것&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1751171176609&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int parse_int(const char *str);  // str은 NULL일 수 있음&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 반환값 또는 출력 인자에서 오류 정보를 명확히 표현하라&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;성공/실패 여부를 int, bool, enum 으로 명확히 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1751171226659&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int load_file(const char *path, char *buf, size_t size); // 성공시 0, 실패시 -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. assert() 는 내부 로직 검증용으로만 사용하라&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;assert() 함수란? 디버깅 모드&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;에서 개발자가 오류가 생기면 치명적일 것이라고 생각하는 곳에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;심어 놓는 에러 검출용 코드.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;프로그램의 전제조건을 확인할 때 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1751171260461&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assert(ptr != NULL);  // ptr은 절대 NULL이 아니어야 함&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 중앙 집중식 오류처리 전략을 설계하자&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 함수에서 오류를 직접 처리하기 보다는, 상위레벨 함수에서 에러 코드를 받아 처리하는 방식이 유지보수에 유리하다. &lt;span style=&quot;color: #ee2323;&quot;&gt;=&amp;gt; 이부분 나중에 더 공부해보자. 프로프레임의 오류처리 방식도 이런 방식임&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1751171426324&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int ret = read_config();
if (ret != 0) {
    log_error(&quot;Config 읽기 실패&quot;);
    return EXIT_FAILURE;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 에러코드 체계화 및 문서화&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;enum&lt;/span&gt;&lt;span&gt; 또는 &lt;/span&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt;을 사용하여 &lt;/span&gt;에러 코드를 구분하고 일관성 있게 정의&lt;span&gt;한다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1751171491736&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define ERR_FILE_NOT_FOUND -1
#define ERR_INVALID_PARAM  -2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c에는 예외처리 기능이 없어서, 명시적이고 일관된 오류 처리 전략이 필요하다.. 방어적 프로그래밍에 대해 다음에 더 알아보자&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/66</guid>
      <comments>https://hr-crypto.tistory.com/66#entry66comment</comments>
      <pubDate>Sun, 29 Jun 2025 13:32:52 +0900</pubDate>
    </item>
    <item>
      <title>[C] 헷갈리는 연산자 우선순위</title>
      <link>https://hr-crypto.tistory.com/65</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;*p.f&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;. 은 * 보다 우선함.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기대 : p가 가리키는 곳의 f필드 (*p).f&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 결과 : p의 f 오프셋이 가리키는 곳의 값 *(p.f)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;이를 해소하기 위해 p-&amp;gt;f 연산자를 만들었다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;int *ap[]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[]가 *보다 우선함&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기대 : ap는 int 배열을 가리키는 포인터 int(*ap)[]&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 결과 : ap는 int를 가리키는 포인터의 배열 int *(ap[])&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;int *fp()&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수 ()가 *보다 우선함&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기대 : fp는 int 값을 반환하는 함수 포인터 int (*fp)()&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 결과 : fp는 int 포인터를 반환하는 함수 int *(fp())&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(val&amp;amp;mask != 0)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;==와 != 는 비트 연산자보다 우선함&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기대 : (val&amp;amp;mask) != 0&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 결과 : val &amp;amp; (mask != 0)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;c=getchar() != EOF&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;==와 != 는 대입 연산자보다 우선함&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기대 : (c=getchar()) != EOF&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 결과 : c=(getchar() != EOF)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;msb&amp;lt;&amp;lt;4 + lsb&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;산술연산자는 시프트연산자보다 우선함&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기대 : (msb&amp;lt;&amp;lt;4) + lsb&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 결과 :&lt;span&gt; msb&amp;lt;&amp;lt;(4+lsb)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;i = 1, 2;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;, 는 모든 연사자 중 가장 우선순위가 낮음&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기대 : i = (1,2);&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 결과 :&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(i=1),2&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주의하자!!&lt;/span&gt;&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/65</guid>
      <comments>https://hr-crypto.tistory.com/65#entry65comment</comments>
      <pubDate>Tue, 24 Jun 2025 22:34:22 +0900</pubDate>
    </item>
    <item>
      <title>[C] 메모리 초기화 함수 bzero(), memset()</title>
      <link>https://hr-crypto.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. bzero() 란?&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1882&quot; data-origin-height=&quot;1684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzIQAe/btsOMRMRbq8/XmoK0duoKSl7OxxqSbPpUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzIQAe/btsOMRMRbq8/XmoK0duoKSl7OxxqSbPpUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzIQAe/btsOMRMRbq8/XmoK0duoKSl7OxxqSbPpUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzIQAe%2FbtsOMRMRbq8%2FXmoK0duoKSl7OxxqSbPpUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1882&quot; height=&quot;1684&quot; data-origin-width=&quot;1882&quot; data-origin-height=&quot;1684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bzero함수는 c언어에서 메모리 초기화 함수로 쓰이고, 포인터 s부터 값을 n byte만큼 0으로 초기화 해주는 함수이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(n이 0이면 아무 동작도 안함)&amp;nbsp;표준 c 라이브러리에 포함되어 있고, 링커에서 -lc로 링크됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. memset() 란?&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1882&quot; data-origin-height=&quot;1684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUC25u/btsOLud7Ihg/8xI1ArgrNwQr9p1fwSwgr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUC25u/btsOLud7Ihg/8xI1ArgrNwQr9p1fwSwgr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUC25u/btsOLud7Ihg/8xI1ArgrNwQr9p1fwSwgr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUC25u%2FbtsOLud7Ihg%2F8xI1ArgrNwQr9p1fwSwgr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1882&quot; height=&quot;1684&quot; data-origin-width=&quot;1882&quot; data-origin-height=&quot;1684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memset()도 마찬가지로 메모리 초기화 함수인데, bzero()랑 다르게 메모리 블록을 특정 바이트 값으로 채우는 함수이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포인터 b부터 시작해서 len 바이트를 c(int 타입인데 내부적으로 unsigned char로 변환)로 채움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.&amp;nbsp; 주의할 점&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) bzero() 대신 memset() 쓰기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bzero()는 POSIX 표준에서 deprecated 됨. memset()은 C 표준에 포함되어있고, 성능 측면에서도 컴파일러가 최적화하기 좋음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜? ISO C 표준함수에 포함되어있어, 더 좋은 명령어로 바꿀 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일러는 memset() 을 내부적으로 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;__builtin_memset()&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;으로 바꾸는데, 이는 컴파일러가 직접 최적화 가능한 특수 명령임. -&amp;gt; 컴파일러는 함수 호출 없이 rep stosb 같은 빠른 명령어 생성 or SIMD 벡터 명렁올 대체한다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;bzero()는 비표준이기 때문에 그냥 함수 호출처럼 취급해서 인라인 처리 불가, 최적화 어렵다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) memset으로 포인터 초기화 할 때&lt;/h4&gt;
&lt;pre id=&quot;code_1750597411938&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 위험한 초기화 방법
memset(&amp;amp;ptr, 0, sizeof(ptr));  // (o)
memset(ptr, 0, sizeof(*ptr));  // (x) 메모리 할당 전에 쓰면 crash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;malloc 없이 포인터를 memset() 하면 세그멘테이션 오류가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포인터 변수 자체를 초기화할지, 가리키는 대상 메모리를 초기화할지 구분하자!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)&lt;/p&gt;
&lt;pre id=&quot;code_1750597624732&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int *ptr;
memset(&amp;amp;ptr, 0, sizeof(ptr));  // (o)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;amp;ptr은 포인터 변수 자체의 주소이다. 주소 자체를 0으로 초기화하는 함수. 이건 ptr 자체를 null로 만들어서 안전하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)&lt;/p&gt;
&lt;pre id=&quot;code_1750597691048&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int *ptr;  //  초기화 안 됨
memset(ptr, 0, sizeof(*ptr));  // (x) &amp;mdash; segfault 가능&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ptr은 가리키는 메모리 주소가 쓰레기값이다. 그 쓰레기 주소에 0을 쓰려고 하므로 segfault 가능.. 매우 위험!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1750597748354&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int *ptr = malloc(sizeof(int));  // 1.메모리 먼저 할당
memset(ptr, 0, sizeof(*ptr));    // 2.이제 안전하게 초기화&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ptr은 이제 유효한 메모리를 가리킨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*ptr은 그 메모리 공간의 값 (int 4바이트)를 의미하므로, memset()은 ptr이 가리키는 곳에 안전하게 접근 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/64</guid>
      <comments>https://hr-crypto.tistory.com/64#entry64comment</comments>
      <pubDate>Sun, 22 Jun 2025 22:14:56 +0900</pubDate>
    </item>
    <item>
      <title>[기사] &amp;ldquo;30년뒤에 시총 3조달러&amp;rdquo;&amp;middot;&amp;middot;&amp;middot;&amp;lsquo;젠슨황 악재&amp;rsquo; 재해석한 아이온큐 韓창업자</title>
      <link>https://hr-crypto.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;250111&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3줄 요약]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;젠슨 황의 &quot;유용한 양자컴퓨터는 20~30년 뒤 가능&quot; 발언으로 아이온큐 주가가 40% 이상 폭락.&lt;/li&gt;
&lt;li&gt;엔비디아가 gpu를 90년대에 만든 뒤 인공지능에 활용되기까지 30년이 걸렸으며, 아이온큐 창업자 김정상 교수는 이 발언을 &quot;30년 후 시총 3조 달러 양자컴퓨팅 기업 가능성&quot;으로 재해석.&lt;/li&gt;
&lt;li&gt;양자컴퓨팅은 장기적인 혁신 분야로, 30년 내 개인이 활용할 수 있는 시대가 올 것이라고 전망.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[시사점/개인 의견 3가지]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새로운 기술 분야에서 긴 개발 주기를 투자자들에게 이해시키는 전략적 커뮤니케이션도 중요함을 느꼈다.&lt;/li&gt;
&lt;li&gt;엔비디아의 gpu 사례로 양자컴퓨팅의 성장 가능성을 예측한 만큼, 인프라 시스템 구축이 핵심 과제가 될 것으로 생각한다.&lt;/li&gt;
&lt;li&gt;양자컴퓨팅은 장기적 투자 관점에서 혁신적인 기회이며, 시장의 신뢰 구축이 중요할 것으로 보인다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[링크] &lt;a href=&quot;https://www.mk.co.kr/news/stock/11215373&quot;&gt;https://www.mk.co.kr/news/stock/11215373&lt;/a&gt;&lt;/p&gt;</description>
      <category>경제</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/62</guid>
      <comments>https://hr-crypto.tistory.com/62#entry62comment</comments>
      <pubDate>Sat, 11 Jan 2025 14:21:45 +0900</pubDate>
    </item>
    <item>
      <title>[기사] 2025년은 양자과학기술의 해 올해 관련사업에 1980억 투자</title>
      <link>https://hr-crypto.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;250109&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3줄 요약]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;과학기술정보통신부는 올해를 양자 산업화의 원년으로 삼고, 지난해 대비 54.1% 증가한 1980억 원의 예산을 투자해 양자종합계획 수립과 플래그십 프로젝트를 추진.&lt;/li&gt;
&lt;li&gt;양자기술산업법에 따라 5년마다 범부처 계획을 수립하며, 올해는 양자컴퓨터&amp;middot;양자통신 분야 중심의 국가 차원 대규모 연구개발을 본격적으로 시행.&lt;/li&gt;
&lt;li&gt;유엔이 올해를 세계 양자과학기술의 해로 지정함에 따라, 정부는 이를 계기로 한국 양자기술 산업화 기반을 마련하고 국제적 경쟁력을 강화하는 데 주력.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[시사점/개인 의견 3가지]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;양자컴퓨팅 기술 발전에 따라 금융권도 양자내성암호 체계 도입 등 보안 전략을 마련해야 할 필요성이 커지고 있음.&lt;/li&gt;
&lt;li&gt;정부가 연구비를 줄이는 와중에도 양자과학기술 투자를 확대하는 것은 해당 기술의 중요성과 국가적 우선순위를 반영한 것으로 보임.&lt;/li&gt;
&lt;li&gt;유엔이 양자과학기술의 해를 지정한 만큼, 국제 표준화와 글로벌 협력 강화를 위한 외교적 노력또한 중요하다고 생각함.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[링크] &lt;a href=&quot;https://www.mk.co.kr/news/it/11214018&quot;&gt;https://www.mk.co.kr/news/it/11214018&lt;/a&gt;&lt;/p&gt;</description>
      <category>경제</category>
      <author>HHRR</author>
      <guid isPermaLink="true">https://hr-crypto.tistory.com/61</guid>
      <comments>https://hr-crypto.tistory.com/61#entry61comment</comments>
      <pubDate>Sat, 11 Jan 2025 14:03:15 +0900</pubDate>
    </item>
  </channel>
</rss>