동적할당을 한뒤에 접근을 할 때에 관한 질문입니다.

somedayhow의 이미지

1. 아래 코드 대로 컴파일을 하고 디버깅을 시작했습니다.

자꾸 건드리다 보니까 자료구조에 대해서 궁금증이 생겨서 메모리를 어떻게 할당받는가를 지켜봤습니다.

첨부한 스크린샷에 나온것처럼

&(Dendrites[0][9]) = 0x6020b8
&(Dendrites[1][0]) = 0x6020d0

이렇게 나왔습니다. 다른 것들도 양상이 비슷합니다.

여기서 궁금한것은

메모리 할당을 근처에 받은것은 이해가 가지만

여기서 0x6020c0와 0x6020c8 은 어디에 갔는가라는 겁니다.

여기에는 뭐가 할당된 것일까요?

디버깅에서 주소를 이용해 그곳에 저장된 값을 찾는 명령어를 찾아봤지만

addr도 아니고 info symbol도 아니고 관련 명령어를 찾지 못해서 무엇이 들어있는지를 확인 못했습니다.

그리고 제가 할당한것은

분명히 10 * 10 배열인데

display /x &Dendrites[1][12] 등 10이 넘는 공간에도 메모리가 할당된것처럼 보이게 나타납니다.

참고로 &Dendrites[1][12] = &Dendrites[2][0] 으로 나왔습니다.

동적할당에 대해 이해를 했다가 싶다가도

이런 결과를 보니 원리를 알다가도 잘 모르겠습니다.

#include <stdio.h>
#include <stdlib.h>
struct Dendrite
{
	double Weight ;
};
 
struct sungjuk
{
	struct Dendrite * Dendrites;
	char name;
	int jumsu;
};
 
void sum( struct sungjuk *);
int main()
{
	int i,j,DendriteCount,DataCount;
	printf("DendriteCount = ?\n");
	scanf("%d",&DendriteCount);
	getchar();
	printf("DataCount = ?\n");
	scanf("%d",&DataCount);
	struct Dendrite **Dendrites;
	Dendrites = (struct Dendrite **)malloc( sizeof(struct Dendrite *) * DataCount ) ;
 
	for(i = 0 ; i < DataCount ; i++)
	{
		Dendrites[i] = (struct Dendrite *)malloc(sizeof(struct Dendrite) * DendriteCount);
	}
struct sungjuk *data ;
 
	data=(struct sungjuk *)malloc(sizeof(struct sungjuk) * DataCount);
 
	for(i = 0 ; i < DataCount ; i++)
	{
		data[i].Dendrites = Dendrites[i];
	}
 
 
2. 동적할당을 한 메모리에 접근을 할때에 관한 질문입니다.
 
<code>
for(i = 0 ; i < DataCount ; i++)
	{
		data[i].Dendrites = Dendrites[i];
	}
 
이 코드를 통해 동적할당한 이차원배열 Dendrites를
 
data[i].Dendrites와 연결을 했습니다.
 
지금이야 DataCount가 10, DendriteCount=10으로
 
메모리 할당을 적게 했기 때문에 별 문제가 없겠지만
 
할당한 공간이 커져서 연속된 메모리공간에 할당을 못했을때
 
즉, &Dendirtes[1][1506] 과 &Dendrites[1][1507] 이 차이가 나는, 두 공간으로 떨어져야 하는 상황과 같은
 
저 코드로 두 구조체를 연결시키지 못할 상황이 발생할 가능성이 있을것 같습니다.
 
그런 상황에서는 어떻게 연결을 해야할까요?
 
이중 루프를 통해 하나하나 연결을 해줘야 할까요? data[i].Dendrites[j] = Dendrites[i][j] 와 같이요
 
간단한것 같지만 큰 데이터를 다룰때 비효율적인건 같아서 좋은 방법이 있나 질문을 드립니다.
 
아예 위 코드는 Segmentaion fault가 발생해 버리네요..
 
컴파일은 성공하지만
data[0].Dendrites[0] = Dendrites[0][0] 부터, 처음부터 에러가 발생합니다.
 
디버깅한 결과에서 보이듯
 
data를 동적할당했지만
 
data.Dendrites[j]에는 0x0과 같은 매우 낮은 주소값이 들어있어서 접근하지 못하기 때문인것으로 보입니다.
 
data[i].Dendrites에 Dendrites[i]를 넣어주면
 
어차피 배열이므로 data[i].Dendrites[j] , Dendrites[i][j]가 되겠지만
 
메모리가 부족하여 한배열이 두공간으로 나누어지는 공간에서는 어떻게 접근해야할까요?
 
 
 
3.gdb 디버거 명령어 관련질문입니다.
 
whatis 와 display or print를 연결할수가 없을까요??
 
즉 데이터형과 주소 모두 보고싶을때는 어떻게 할 수 있을까요?
 
그리고 display를 통해 나타낸 변수목록을 저장하는 방법이 있나요?
 
컴파일 할때마다 새로 display 변수명 을 적어야 하니 꽤나 불편하네요
 
 
긴 질문을 읽어주셔서 고맙습니다. (__)
 
 
아래는 전체 코드입니다.
 
<code>
#include <stdio.h>
#include <stdlib.h>
struct Dendrite
{
	double Weight ;
};
 
struct sungjuk
{
	struct Dendrite * Dendrites;
	char name;
	int jumsu;
};
 
void sum( struct sungjuk *);
int main()
{
 
	int i,j,DendriteCount,DataCount;
	printf("DendriteCount = ?\n");
	scanf("%d",&DendriteCount);
 
getchar();
 
	printf("DataCount = ?\n");
	scanf("%d",&DataCount);
	struct Dendrite **Dendrites;
 
 
	Dendrites = (struct Dendrite **)malloc( sizeof(struct Dendrite *) * DataCount ) ;
 
	for(i = 0 ; i < DataCount ; i++)
	{
		Dendrites[i] = (struct Dendrite *)malloc(sizeof(struct Dendrite) * DendriteCount);
	}
 
 
	struct sungjuk *data ;
 
 
	data=(struct sungjuk *)malloc(sizeof(struct sungjuk) * DataCount);
 
 
 
	for(i = 0 ; i < DataCount ; i++)
	{
 
  		data[i].Dendrites = Dendrites[i];
	}
 
	sum (data);
 
	for( i=0 ; i<10 ; i++)
	{
		data[i].jumsu+=1*10;
		for(j=0 ; j < 10 ; j++)
		{ 
			data[i].Dendrites[j].Weight = 1;
			printf("data[%d].jumsu = %d \n",i,data[i].jumsu);
		printf("Weight[%d]  = %lf \n",i,data[i].Dendrites[j].Weight);
		} 
	}
	for ( i = 0 ; i < DataCount ; i++)
	{
		free(Dendrites[i]);
	}
	free(Dendrites);
	printf("%ld\n",sizeof(Dendrites));
	return 0;
}
 
void sum(struct sungjuk *sung)
 
{
	int tot=0,i;
	for(i =0 ; i<10 ; i++)
	{
		sung->Dendrites[i].Weight=0;
		sung[i].jumsu+=10;
	}
}

File attachments: 
첨부파일 크기
Image icon 영역_001.jpeg152.48 KB
yhsuk의 이미지

원하는 답변일지는 모르겠지만 malloc 호출시마다 할당되는 주소값은 추정하면 안됩니다.
컴파일러(또는 OS)의 할당 알고리즘에 따라 할당을 하는 것이지, 연속으로 호출되었는데, 버려지는 것 같은 빈공간이 생기는 것에 대해서까지 고민할 필요는 없어보입니다.
(액세스 속도를 위해서일 수도 있고, realloc등의 여지를 생각해서 그런 방법을 취했을 수도 있고..)

somedayhow wrote:

분명히 10 * 10 배열인데
display /x &Dendrites[1][12] 등 10이 넘는 공간에도 메모리가 할당된것처럼 보이게 나타납니다.
참고로 &Dendrites[1][12] = &Dendrites[2][0] 으로 나왔습니다.

=> 이런건 우연입니다. 기본적으로 인덱스 바운더리 검사를 하지 않습니다. Segfault가 날 수도 안날 수도 있습니다. 인덱스를 범위 넘어서 사용하지 않는 것은 전적으로 코드 만드는 사람의 책임이 됩니다.

somedayhow wrote:

        for(i = 0 ; i < DataCount ; i++)
	{
		data[i].Dendrites = Dendrites[i];
	}


이 코드를 통해 동적할당한 이차원배열 Dendrites를 data[i].Dendrites와 연결을 했습니다.
지금이야 DataCount가 10, DendriteCount=10으로 메모리 할당을 적게 했기 때문에 별 문제가 없겠지만
할당한 공간이 커져서 연속된 메모리공간에 할당을 못했을때

즉, &Dendirtes[1][1506] 과 &Dendrites[1][1507] 이 차이가 나는, 두 공간으로 떨어져야 하는 상황과 같은
저 코드로 두 구조체를 연결시키지 못할 상황이 발생할 가능성이 있을것 같습니다.
그런 상황에서는 어떻게 연결을 해야할까요?

=> 정답이 없는 내용이 아닐까 합니다.
프로그램이 실행되는 초기에 충분하게 연속된 공간을 할당받아 풀링 기법을 사용할 수도 있고(이 경우엔 실행 초기에 연속된 공간을 할당받지 못하면 메모리 부족등의 메시지를 출력하고 종료)
아니면 알고리즘을 바꿔서 큰 메모리 공간이 필요없게 만들거나,
아니면 하나의 엔트리에 필요한 공간을 절약해서(구조체 pack, 비트 사용등) 하는 방법도 있고,
그런데 생각하고 고민하는 자세는 좋지만, 조금은 하나씩 하나씩 해결하는 게 좋지 않을까 합니다. (너무 많은걸 한꺼번에 생각하면 머리만 아프고 일은 손에 안잡히고.. 쩝)
일단은 DataCount나 DendriteCount등의 최대값을 한정시키고 사용하는 것도 어느 정도 쓸만합니다. (귀찮아서 그럴수도 있지만..)
물론 요구되는 사항이 근 시일내에 저 최대값을 넘길 가능성이 있다면 처음부터 고민을 해야겠지만요.

somedayhow wrote:

이중 루프를 통해 하나하나 연결을 해줘야 할까요? data[i].Dendrites[j] = Dendrites[i][j] 와 같이요
간단한것 같지만 큰 데이터를 다룰때 비효율적인건 같아서 좋은 방법이 있나 질문을 드립니다.

아예 위 코드는 Segmentaion fault가 발생해 버리네요..

컴파일은 성공하지만
data[0].Dendrites[0] = Dendrites[0][0] 부터, 처음부터 에러가 발생합니다.

=> data[i].Dendrites에 동적할당을 수행한 적이 없으니 data[i].Dendrites[j] = Dendrites[i][j] 이런 코드는 Seg Fault를 발생시킵니다.

Signature :) - "여유를 갖고 행동하되 게을러지지 말자"

somedayhow의 이미지

궁금한게 많이 해소되었습니다.

많이 배웠습니다^^

말씀하신것처럼 조금씩 하나하나 해결해가는 자세가 필요할때인것도 같습니다.

이제 프로그래밍을 시작해서 그런지, 자꾸 궁금증이 생기더라구요 ㅎㅎ

같은 연구실사람도 자기도 한때는 그랬다고하네요. 저도 방향을 잘 잡아야겠습니다.

for(i = 0 ; i < DataCount ; i++)
{
data[i].Dendrites = Dendrites[i];
}

위와 같은 상황은 아예 data[i].Dendrites = (struct *Dendrite)malloc(sizeof)~~ 와 같이
Dendrites[i]에 메모리할당없이
data[i].Dendrites에 메모리 할당을 해주고 여기에 데이터를 담아도 해결이 되는것 같습니다.
코드가(수식이) 너무 길어진다는 문제가 발생하지만 ㅠ

----------------------------------------------------------------------------------------------------------------------
많이 배워갑니다
고맙습니다.
언젠가 질문이 아니라 답변을 달아줄 수 있는 날이 오기를

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.