배열 백만개 만드는 중...

dokin의 이미지

이게 무식한 방법이라는거, linked list를 써야 하는게 바람직 한 것이라는 것은 압니다 -_-;; 하지만 배열 써서 하랍니다.

예전에도 백만개의 정수를 int배열 백만개를 써서 file에서 fscanf("%d")로 그걸 다 불러와 무식하게 계산하는 플그램을 시켜서 그건 잘돌아갔었는데요... 지역변수로 int data[1000000]; 써도요.

이번에도 그런식으로 이번엔 다음과 같은 structure

typedef struct Tel_book{
char name[32];
unsigned int number;
Department dept;
}Tel_book;

를 백만개 만들라고 해서 그냥 되겠지 하고 시키는대로 했더니 바로 세그먼트 오류....

웃기는 건 이렇게 하고 지역 변수로

Tel_book tel_book[301000];

이라고 선언 후 fopen, fscanf 하면 잘돌아가는게 똑같은 걸 전역 변수로 선언하면 또 세그먼트 오류...;;

지역 변수로 Tel_book tel_book[400000]; 이상 큰 값을 써주면 세그먼트 오류....

이유를 모르겠습니다... 여기 뒤지다가 백만개 짜리 정도의 큰 배열은 전역변수로 해보란 얘기가 있어 해봤더니 오히려 같은 값에서도 세그먼트 오류...;

파일 함수는 fopen, fscanf 밖에 안 씁니다...

if(!(addr_book = fopen("addr_book.txt", "r")))
{
에러 문구 출력하고 종료해라...
}

for(counter=0;counter<300000;counter++)
{
fscanf(addr_book, "%s %s %s %s", tel_book[counter].name, temp_name, number, depart);

for문으로 백만번 fscanf 돌리고요... 이건 예전에도 문제 없었으니 상관없을꺼라고 봅니다만...;

혹시 string.h 함수를 써서 그런가 싶기도 합니다. fscanf로 파일에서 XXX)XXX-XXXX라고 있는 전화번호를 string으로 읽어서, strncpy, strncat으로 다른 string에 XXXXXXXXXX ->10개 자리의 )와 -를 뺀 char배열 만든 후 마지막으로 atoi 써서 int로 변환...

하지만,

strcat(tel_book[counter].name, temp_name);
strncpy(tran_num, ptr_num, 3);
ptr_num += 4;
strncat(tran_num, ptr_num, 3);
ptr_num += 4;
strncat(tran_num, ptr_num, 4);
tel_book[counter].number = atoi(tran_num);

보시듯이 모두 임시 char배열을 쓰기 때문에 맨 첫줄의 strcat을 제외하곤 tel_book[300000]은 건드리지도 않는데... 당연히 주석 처리 후 돌려봤습니다.. 심지어 저 문구들 전체를 주석으로 처리해도... 세그먼트 오류

세그먼트 오류만 보면 이제 노이로제 걸릴려 합니다;;; 방법 없을까요...

위의 structure를

Tel_book* tel_book;

tel_book = (Tel_book*)malloc(sizeof(Tel_book));

해도 세그먼트 오류나고...;;

참고로 struct Tel_book은 40바이트이고, 따라서 지역변수 301000개를 해서 잘돌아가는 버젼으로는 1204만 byte짜리 배열이 만들어 집니다. 1001000개 4004만 byte가 목표이구요... Department라는건
typedef enum {Accounting, Sales, Control, Maintenance, Security, Information} Department;
으로 선언한 int입니다.

dokin의 이미지

배열이 길어서 에러가 나는게 아니었습니다. 문제가 있던 부분은
ptr_num += 4;
바로 이부분 이었습니다...

windows기반에서 작업할때는 배열선언 후 그 배열 명칭에 바로 다음과 같이 포인트 연산을 붙여도 아무 문제없이 잘 돌아가는데, 리눅스에선 배열을 선언하고 포인트 연산이 안되길래, 배열에 ptr_num이란 포인터를 붙여서 포인터 연산을 시킨건데, 이렇게하면 컴파일 에러는 피하지만 배열의 주소를 옮기려 하는 과정에서 세그먼트 오류가 나는군요.

배열을 쓰지 않고 바로 포인터부터 선언한 이후에,
ptr_num = (char *)malloc(13);

이런 식으로 동적할당을 하고 포인터 연산을 동일하게 수행하자 세그먼트 오류없이 잘 넘어갔습니다...

혹 같은 걸로 헤매는 분이 나중에 있을까 싶어 남깁니다...

"windows기반에서는 가능한 배열을 기반으로한 포인터 연산이, linux에서는 세그먼트 오류를 내고, 이를 피하려면 포인터로 선언 후 메모리 동적 할당을 해야한다."

modestcode의 이미지

Quote:
배열이 길어서 에러가 나는게 아니었습니다. 문제가 있던 부분은
ptr_num += 4;
바로 이부분 이었습니다...

초기화 되지 않은 변수에 연산은 undefined behavior입니다. C 매뉴얼을 참고하시기 바랍니다.
dokin의 이미지

배열로 선언 후, 초기화만 시키면 포인터 연산이 문제없이 잘 된다는 뜻이군요, 리눅스에서도??

초보자에게 조언 감사합니다 -_- 꾸벅...

그럼 다음과 같이 명제를 바꿔야 겠군요.

"windows에서는 포인터나 배열의 초기화 없이도 포인터 연산이 가능하나, 리눅스에서의 포인터 연산을 위해서는 그 전에 반드시 초기화를 시켜주어야 한다."

harisoo의 이미지

리눅스에서도 배열이나 포인터 둘다 연산 가능합니다.
그리고 포인터가 가리키는 주소가 유효하지 않을 경우 세그먼트폴트가 발생됩니다.
윈도우이든 리눅스이든 상관없습니다. 다만 윈도우에서 발생되지 않은건 운이라고 생각됩니다.

dokin의 이미지

....

dokin의 이미지

배열이든 포인터이든 가리키는 주소에 dummy 값이 들어있더라도 일단 실행하고 봅니다.

따라서 말도 안되는 연산이 종종 일어나죠. 리눅스처럼 세그먼트 오류라고 뱉어내지 않고요.

'유효한 주소'라는 말이 정확히 어떤 말씀이신진 모르겠으나, 일단 배열이나 포인터로 지정했으니 리눅스에서도 유효한 주소인 것 같습니다. 단, 리눅스는 유효한 주소여도 그 안의 값이 초기화가 되어있어야 오류를 뱉지 않는다는게 윗분 말씀인거 같은데요.

dokin의 이미지

...

goguma의 이미지

일찍 알았다면 더 좋을뻔 했군요..ㅡㅡㅎ
예전에 삽질 후 결국은 다시 짰던.....ㅡㅡ
--------------------------------
스물셋.. 독립.. 열심히 살아보자!!
--------------------------------

--------------------------------
스물셋.. 독립.. 열심히 살아보자!!
--------------------------------

익명 사용자의 이미지

음... 대충 내용을 보아하니...

메모리 문제로 보입니다.
1백만개의 배열데이터라면 메모리에서 상당한 크기로 잡힙니다.
이때에 정적으로 배열잡을 수 있는 크기가 있습니다.
이 크기를 넘어가면 에러가 나지요.

tel_book = (Tel_book*)malloc(sizeof(Tel_book));

이거는 sizeof(Tel_book)다시 표현하면 Tel_book 사이즈만큼의 메모리 할당이지
1백만개의 메로리 할당이 아닙니다.

이럴 때는 calloc()를 써야 합니다.
tel_book = (Tel_book*)calloc(1000000, sizeof(Tel_book));

나중 메모리 해제 free()는 꼭 해주시구요.

도움이 되길...

dokin의 이미지

tel_book = (Tel_book*)malloc(1000000*sizeof(Tel_book));

이렇게 했었지요 ^^; 지적 감사합니다~

문제는 이곳에 있는게 아니라, 배열 선언 후 배열의 값을 초기화 하지 않은 상태에서, 포인트 연산을 하면 에러가 난다... 고 일단락났습니다. 배열을 tel_book[1001000]과 같이 써도 잘 돌아가더군요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.