C언어 코딩 오류 질문입니다..

yache1217의 이미지

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
FILE* ip;
FILE* op;
 
typedef struct Graph* Graph;
struct Graph{
    int* node;
    int size;
    int** matrix;
};
 
Graph CreateGraph(int* nodes);
 
int main(int argv,char* args[]) {
    ip = fopen(args[1],"r");
    op = fopen(args[2],"wr");
 
    char *line;
    size_t len = 0;
    len = getline(&line,&len,ip);
    int arr_index = 0;
    int *arr = malloc(sizeof(int)*((len-1)/2));
    char *ptr = strtok(line, " ");
    while(ptr != NULL){
        arr[arr_index++] = atoi(ptr);
        ptr = strtok(NULL," ");
    }
 
    Graph graph = CreateGraph(arr);
}
 
Graph CreateGraph(int* nodes){
    int matrix_tmp[sizeof(nodes)/4][sizeof(nodes)/4] = {{0,},{0,}}; //size 수정
    Graph temp = { nodes, sizeof(nodes) / 4, matrix_tmp};
    for(int i=0 ; i<temp->size ; i++){
        printf("%d",temp->node[i]); //테스트
    }
    return temp;
}

일단 전체코드가 아닌 질문에서 필요한 부분만 잘라서 올리겠습니다.
문제가 되는 부분은 CreateGraph(arr)이 부분인데요 질문할 부분이 2가지 정도가 있습니다.
1. CreateGraph(arr)에서 arr을 넘긴 뒤 제가 원하는 것은 Graph temp의 int* node에 제가 넘긴 arr을 넣는것입니다. 그런데 뜻대로 되질 않네요 ㅠㅠ 먼저 테스트 해볼려고 temp->node[i]를 printf하려고 했지만 여기서부터 말썽입니다. 먼저 저상태에서 warning으로 incompatible pointer types initializing 'Graph'~~ 이게 뜨는데 여기서 자동완성을 하면 node가 (Grapg)node로 형변환되게 바뀝니다.. 이것도 이해가 되질 않네요..

2.arr 배열의 주소를 넘긴 뒤 그 크기만큼 이중배열을 만들고 싶은데요 아무래도 주소를 넘기다 보니까 sizeof(arr)하면 주소의 크기인 8이 나오더라구요 저 CreateGraph함수내에서 배열의 크기를 알 수 있는 방법은없을까요..?

++)디버그모드로 했을시에 나오는것도 사진첨부로 올렸습니다.

File attachments: 
첨부파일 크기
Image icon 캡처.PNG52.05 KB
익명 사용자의 이미지

음...;;

1. typedef struct Graph* Graph;

이러면 Graph는 struct Graph에 대한 포인터를 나타내는 typedef 이름이 됩니다.

그걸 의도한 게 맞나요?
이런 식으로 쓰지 말라는 법은 없긴 하지만, 코드를 짠 사람은 이게 무엇을 의미하는지 명확하게 이해하고 있어야 합니다.

Graph가 사실은 포인터라는 점을 명심하고 CreateGraph 함수 내부를 다시 살펴보세요. 뭐가 이상한지 보이기 시작할 겁니다.

2. C언어에서 매개변수로 넘어온 배열의 크기를 알 수 있는 일반적인 방법은 없습니다.

(1) 일단 애초에 CreateGraph 함수에 배열을 넘기려던 것도 아니네요. int *arr = ...에서 arr는 누가 봐도 배열을 만든 게 아니라 포인터입니다.

(2) 물론 그 포인터에 malloc으로 할당한 메모리를 담긴 했죠. 근데 C언어에서 malloc으로 할당한 메모리의 크기를 사후에 알 수 있는 이식성 있는 방법이 없어요.

네, _msize나 malloc_usable_size 같은 함수가 있기는 하다는 거 알고 드리는 말씀입니다. 별로 권장하고 싶지는 않지만, 꼭 그렇게까지 하고 싶다면야...

(3) 근데 _msize나 malloc_usable_size 같은 함수를 쓴다 해도, 애초에 중요한 건 할당된 크기가 아니라 실제로 들어가 있는 유용한 데이터의 갯수, arr_index가 아니던가요?

이거는 정말로 호출한 쪽이 알려주지 않으면 알 수가 없죠.

요약하면, 그냥 애초에 호출하는 쪽에서 배열의 크기도 같이 넘겨주게 만들어야 한다는 겁니다.

익명 사용자의 이미지

만일을 대비해서 질문 원본을 기록으로 남겨둡니다.

https://archive.is/tNypE

yache1217의 이미지

답변내용이 큰 도움이 되었습니다. 먼저 typedef struct Graph* Graph; 이 부분은 과제에서 스켈레톤 코드로 주어진것이여서 미처 그부분까지는 생각하지 못하였네요 ㅠㅠ이부분을 신경써서 수정하니 정상적으로 잘 작동하게되었습니다.
배열의 크기를 넘기지 못하는것은 인자를 제가 수정을할수가 없어서 ㅠㅠ 결국에는 CreateGraph함수 내에서 for문을 돌아 size를 알아내였습니다. 이부분에도 약간의 오류가있지만(size잴라고 for문 돌렸는데 이상하게 입력한 숫자의 수가 6개일때만 뒤에 1041이라는게 붙고 사이즈도 6이 아닌 7로 잡히네요...;;)금방 고칠수도 있을것 같습니다. 혹시몰라 코드 남겨봅니다!

Graph CreateGraph(int* nodes){
    int size = 0;
    for(int i=0 ; nodes[i] ; i++){
        size++;
    }
 
    //printf("size : %d /",size);
 
 
    Graph temp = malloc(sizeof(struct Graph));
    int **matrix_temp = malloc(sizeof(int*)*size);
    for(int i=0 ; i<size ; i++){
        matrix_temp[i] = malloc(sizeof(int)*size);
    }
 
    temp->size = size;
    temp->matrix = matrix_temp;
    temp->node = nodes;
 
    return temp;
}

yache1217의 이미지

생각보다 저 오류의 원인을 고치기가 어렵네요... 다른 갯수일때는 다 잘 작동하고 입력한 숫자의 갯수가 6, 10 (1개부터 30개까지 테스트 해봤습니다.)개일때만 for문을 한번더 돌고 뒤에 1041이 붙네요... 혹시 짐작가시는 부분이 있나요..?

++)strtok에서 오류나 나는듯 합니다
"1 2 3 4 5 6" 을 입력하면 1041이 붙고
"1 2 3 4 5 6 "을 입력하면
lab9: malloc.c:2401: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. 이런오류가 뜹니다.
또 신기하게도
"1 2 3 4 5 6 7 8 9 10" 을 입력하면 뒤에 1041이 붙고
"1 2 3 4 5 6 7 8 9 10 "을 입력하면 정상적으로 작동합니다..;;;

라스코니의 이미지

전체적으로 무엇을 하실려는 건지는 모르겠는데
int *arr = malloc(sizeof(int)*((len-1)/2));
에서 arr[]에는 어떤 값이 들어 있는지 모릅니다. 아마 쓰레기값이겠죠.
사용하기 전에 memset() 등으로 초기화해보세요.

대부분의 오류의 원인은 디버그를 하면 찾을 수 있습니다. line-by-line으로 디버그해보세요.

Stephen Kyoungwon Kim@Google의 이미지

짐작컨대 질문을 좀 구체화하시는 게 나을 것 같아요. 가장 높은 추상 수준에서 도대체 뭘 하자는 코드인지 알기가 어렵습니다.

이 질문은 제가 교수였다 해도 뭐 딱히 과제를 인터넷에서 해결하려는 노력의 일부로 보이지 않을 것 같은데, 안심하시고 문제 자체를 올려보세요.

이름이 그래프니 그래프를 만들려는 거란 건 알겠고, int** matrix이 있으니 아마도 node가 int인 2D Matrix 꼴로 그래프를 표현하려는 거라는 짐작이 됩니다. int* node는 그리 보면 node의 리스트라고 추측되고요. 한데 size는 뭐죠?

그리고 int*가 parameter로 넘어가는데, 넘겨받은 입장에선 익명사용자님 말씀처럼 사이즈를 신뢰성 있고 이식성 있게 말하기 어렵습니다. 따라서 parameter가 그거 하나라면, 사이즈를 알 수 없다고 봐야 합니다. 다만 각각의 node는 int고, 이를테면 1번부터 시작해서 0은 절대 될 수 없다, 라고 한다면 0을 node array의 마지막을 표시하는 마커로 활용할 순 있겠죠. 그런데 그건 좋은 디자인은 아니죠.

익명 사용자의 이미지

저라면 arr이 가르키는 메모리 영역의 첫번째 int값을 valid한 node의 개수로 사용하겠습니다.

Stephen Kyoungwon Kim@Google의 이미지

버퍼와 사이즈를 따로 넘기거나 struct XXX 안에 버퍼와 사이즈를 묶어서 넘기는 게 낫다고 생각합니다. 마커 얘기는 int*만 넘기는 게 별로 말이 안 된다는 의미였습니다.

Anti-Lock의 이미지

이런 질문이 어려운게...

1.실제 문제를 밝히며 물어보지 않는다.
2.질문자가 문제를 제대로 파악했는지를 확인할 수 없다.
3.문제 의도와 관계없이 자기가 하고싶은걸 해달라고 한다.

익명 사용자의 이미지

+ 기껏 답변해주면 "그거 문제조건이라 못바꿔요 ㅜㅜ"

그럴 거였으면 미리 말해줘야지.

댓글 달기

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