unsigned int에 관한 치명적인 경험...

ep6tri의 이미지

#include <stdio.h>
#include <stdlib.h>
#define BUF 100000
 
typedef unsigned int UINT;
 
int main(int argc, char** argv)
{
	UINT i;
	UINT *p = (UINT*)malloc(sizeof(UINT)*BUF);
	for(i = 0 ; i < BUF; i++)
	{
		p[i] = i;
	}
 
	for (i = BUF-1; i >= 0 /* && i < BUF */ ; i-- )
		p[i] = i;
 
	free(p);
	p= NULL;
 
	return 0;
}

QnA 지만 자문자답이랄까요?
찾고 찾고 찾다가 겨우 알게 된 malloc과 free에 관한 치명적인 추억입니다.

어떤 프로그램을 짜다 계속 메모리 문제 때문에 죽는 것입니다...
VC에서는 DAMAGE : After Normal block .... 이런 메시지가 나오고요.

문제를 찾아 보고 원인을 단순화시켜보니 저렇게 되는군요..
희한하게도 typedef 문장에서 unsigned를 signed로 고치면 아무 문제 없이 동작합니다.
하지만 unsigned라면 백발백중 에러입니다...

.. 알고 계신 분은 아시겠지만...
unsigned int 에서 0 - 1은 -1이 아닌 것이 문제였던 것이었습니다.
unsigned int 에서 음수 표현은 없으므로 0-1이면 양수의 가장 큰 값...2의 32승-1이 나오게 되고
프로그램은 어떻게 동작할 지 알 수 없게 되는 거지요..

오버플로우... ㅠㅠ 잘 안다 잘 안다 싶지만.. 언제나 이렇게 뒤통수를 때리는군요.
쓰디쓴 치명적인 추억.. 반성문 적는다는 심정으로 몇 자 이렇게 적어봅니다.

klyx의 이미지

malloc/free와는 전혀 무관한 문제입니다.

Hyun의 이미지

빅 엔디안 머신의 레지스터 비트 선언하면서 아래와 같이 비트를 쉬프트 시켰는데,

#define ABC ((1<<31))>>1)
printf( "%08x\n", ABC );

결과를 보면 0xc0000000 이 나왔던가... 요것도 노치기 쉬운 경우죠.
이것때문에 한 1주일은 고생했다는...
dasomoli의 이미지

빅엔디안 머신을 많이 접해보지 않아서 언급하신 예제가 어떤 의미인지 잘모르겠는데 설명 좀 부탁드려도 될까요?
제가 생각하기엔 리틀 엔디안이라도 같은 결과가 나올 것 같아서요.



dasomoli의 블로그(http://dasomoli.org)
dasomoli = DasomOLI = Dasom + DOLI = 다솜돌이
다솜 = 사랑하옴의 옛 고어.
Developer! ubuntu-ko! 다솜돌이 정석


dasomoli의 블로그(http://dasomoli.org)
dasomoli = DasomOLI = Dasom + DOLI = 다솜돌이
다솜 = 사랑하옴의 옛 고어.
Developer! ubuntu-ko! 다솜돌이 정석
Hyun의 이미지

리틀엔디안 에서도 같은 결과가 나오기는 하지만...
빅 엔디안에서는 리틀엔디안에서와는 달리 MSB에서부터 비트번호가 0번부터 매겨집니다.
그래서 32비트 레지스터에서 N번 비트를 가르키려면

#define 0x80000000>>N

이렇게 선언해야 하는데, 이걸 간단하게 하겠다고
#define (1<<31)>>N

이렇게 선언한게 문제겠죠...
bacon의 이미지

(1u << 31) >>N

cppig1995의 이미지

1. QnA에 올릴 만한 글이 아닙니다.
답을 모르는 상황에서 질문을 올렸다가 검색이나 개인적 소통(personal communication) 등을 통해 답을 알게 되어 직접 답을 올리는 것과 같은 방식으로 하나의 글타래(thread)를 구성했다면 프로그래밍 QnA 포럼에 게시될 글로서 적절했겠지만, 이와 같은 경우 자유 게시판에 올리시는 것을 추천합니다.

2. malloc/free와 관련한 문제가 아닙니다.
앞서 xylosper님의 지적과 같이 제목과 내용이 심하게 잘못되어 있습니다. 지역 변수를 선언함으로써 스택에 기반한 정적 할당을 사용하거나, new/delete(new[]/delete[])를 사용했다면 문제가 없었을지를 생각해 보시기 바랍니다.

여전히 이 문제는 "malloc/free의 탓이다!"라고 생각하신다면, 올리신 글을 요약해 드리겠습니다.
"무부호형을 제어 변수로 하여 하향 for문을 실행할 경우 의도했던 최종 반복(제어 변수=0) 이후 for문의 세 번째 부분에 따라 1을 뺐을 때 최대값이 되어 무한 반복한다."
여기 어디에 malloc이나 free, 동적 할당에 대한 이야기가 있는지 생각해 보세요.



한말글 프로그래밍 언어 "열정" http://me-lang.wo.tc

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

ep6tri의 이미지



라는 제목 때문인지 다들 malloc과 free가 잘못되어서 에러가 났다! 라고 해석하시는 것 같네요.
.. 하지만 제 글 어디에서도 malloc / free 의 탓에 에러가 났다고는 말한 적 없는 것 같은데요..

사실 malloc/free가 까다롭긴 합니다만
저는 오히려 unsigned 최소값 - 1은 최대값이 된다는 것에 초첨을 두고 썼는데...
malloc / free 를 문제라고 생각하지 말라 라는 말씀에 오히려 제가 좀 더 놀랬습니다.
"아 그렇게 생각하셨나 ? .. 에 그런게 아닌데 " 하구요.

제목과 내용을 똑바로 써야지! 라고 말씀하신다면.. 제목을 더욱 내용과 맞게 짓지 못한 제 탓도 있겠습니다만...
그냥 malloc과 free 때문에 고생고생하다 알아낸 과정을 좀 제목에 담아 두고 싶어서 말이죠..
하다보니 정말 두서없는 글이 되었습니다. ㅜㅜ..

또 논리적이거나 기술적인 내용을 정확하게 담아내려는 의도는 그다지 없었구요..

그래서 아까는 '기록하고 싶다'는 생각에 막 적다 보니 QnA에 올려 버렸지만
잘 생각해보니 QnA에는 올릴 만한 건 아닌 것 같아서 뒤늦게 자유게시판으로 옮겼습니다.
(만일 이 일로 기분 상하셨던 회원님이 있었다면 죄송합니다..)

tomahawk28의 이미지

놀라실 일까지는 아닌것 같은데.. 그냥 제목을 unsigned int 때문에 고생한 이야기 정도로
고치면 되지않나요?


Can't stop watching this;;

gurugio의 이미지


아하~ 저도 비슷한 경험이 있습니다.
비슷한 경험을 했으면서도 다시 보니 새롭네요.
한참 들여다 봤습니다.. 흑..

그래서 저는 왠만하면 진짜 왠만하면 unsigned 타입을 안쓰게 되었습니다.
주소값이나 하드웨어 레지스터 값 외에
일반 정수형을 쓸때는 꼭 signed 타입만 쓰도록 생각하고 있습니다.

근데 한가지 웃긴 것은
시간이 지나면 내가 왜 정수형에서 unsigned 값을 안쓰자고 결심했는지를
까먹게 된다는거지요.. 붕어.. ;-)

----
세상을 바꾸는 것은 단 한 사람. 오직 하나님의 사람뿐이다.
http://www.asmlove.co.kr
http://blog.naver.com/gurugio

grassman의 이미지

음수값이 나올 경우가 더 치명적인 경우가 많더군요.
차라리 unsigned 형을 사용하면 0부터 시작하는 index에 대해서는 범위의 최대값만
검사해도 되는 장점이 있습니다.
다만 위와 같은 이유로 loop에서 감소 연산을 최대한 회피하게 되었습니다만...
(위와 같이 bounds checking이 될 경우에는 segment fault 정도지만
0을 최소값으로 할 경우 잘못하면 무한루프를 돕니다)

Hyun의 이미지

위의 경우처럼 unsigned 형에서 0을 최소값으로 비교하면 gcc가 항상 참이라고 경고를 내지 않나요?


chadr의 이미지

다들 많이 겪으신 경험일것이라고 생각합니다.

그래서 저도 가능한 unsigned형은 사용하지 않습니다.
만약에 데이터 범위가 더 커야한다면 그보다 한단계 많은 범위를 표현할 수 있는 자료형을 사용합니다.

물론 메모리 크리티컬한 시스템에서는 예외지만요 :)
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

madman93의 이미지


gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

gcc -W -Wall -o test unsigned_test.c
unsigned_test.c: In function ‘main’:
unsigned_test.c:16: warning: comparison of unsigned expression >= 0 is always true

역시 warning이 더 무섭군요
---------------------------------------------
svn + trac + my project --> success ???
---------------------------------------------

---------------------------------------------
git init
git add .
git commit -am "project init"
---------------------------------------------