minarai
2k
2019-07-25 09:20:16 작성 2019-07-25 09:22:03 수정됨
12
761

C언어 하다가 의문점이 생겨서 질문합니다...


전공자도 아니고
C언어 말고 웹개발 교육받고...
C언어 사용하는 현장에 와서 삽질 중인데요...
어제 터진 오류 원인을 해결을 밨지만 약간 이해가 안되어서 공유합니다.

전부 예제입니다.


아래 구조체가 있고

struct str
{
    char    data1[20];
    char    data2[20];
    char    data3[20];
    char    data4[20];
    char    data5[20];
}


해당 현장에서는 선언단계에서는 null이고 사용하려고 하면 일단
아래처럼 스페이스로 초기화 하고있습니다.(이건 못바꿈)
memset(str.data , ' ' , sizeof(str.data));
memset(str.data2, ' ' , sizeof(str.data2));
memset(str.data3, ' ' , sizeof(str.data3));
memset(str.data4, ' ' , sizeof(str.data4));
memset(str.data5, ' ' , sizeof(str.data5));

str.data1의 데이터를 trim처리를 해서 name에 담고 다른쪽으로 던지려고 하는데


- trim처리
char name[20 + 1];
memcpy( str.data1, "testData            ", 20 ) ;
trim(name, str.data1, sizeof(name), ★strlen(str.data1));


- trim처리 공통모듈
void trim(char *to, const char *from, const size_t to_len, const size_t from_len) {

    int copy_len        ;
    std::string temp_s1 ;
    std::string temp_s2 ;

    temp_s1 = std::string(from, from_len);
    temp_s2 = 트림API(temp_s1); - 전후방 공백 제거
    copy_len = temp_s2.length() < to_len ? temp_s2.length() : to_len;

    memset(to, 0x00, to_len);
    temp_s2.copy(to, copy_len);

    return;
}


여기서 평상시에는 잘 되고있었는데
이 타이밍에 str.data2에 데이터가 들어가는 순간
memcpy( str.data2, "testData2           ", 20 ) ;

str.data1 = "testData1           testData2"

위에처럼 str.data1영역을 넘어서서 testData2영역의 뒤쪽을 trim시켜 버리는 현상이 발생했는데요
strlen을 sizeof로 바꿔서 해결을 보긴 했는데
trim(name, str.data1, sizeof(name), ★sizeof(str.data1));
왜 strlen을 했을때 다른 변수까지 침범하는지 이유를 모르겠네요...
구조체가 문제인건가요




0
0
  • 답변 12

  • Keloper245
    1k
    2019-07-25 09:32:42 작성 2019-07-25 09:36:48 수정됨
    0
  • Chaed
    2k
    2019-07-25 09:40:07
    0
  • minarai
    2k
    2019-07-25 09:41:46

    Keloper245  감사합니다 참고가 되었습니다.

    구조체 변수 사이에는 null문자 등은 어떻게 처리되어지고있는건가요

    저는 변수 사이에 null문자가 있는게 아닌가 싶었는데


    0
  • Keloper245
    1k
    2019-07-25 09:44:42 작성 2019-07-25 09:49:29 수정됨

    \0 -> 이게 널입니다.


    크기를 지정하지 않으면 자동으로 마지막에 \0 붙으나,

    크기를 지정하면 \0을 고려해서 지정해주셔야합니다.


    https://blog.hexabrain.net/16

    0
  • 이뉴
    569
    2019-07-25 09:49:04 작성 2019-07-25 09:50:59 수정됨

    메모리 카피를 꼭 써야하는지에 대해 검토해보세요

    어차피 캐릭터 다룰거라면 안전한 문자열 API 쓰는걸 더 권고 합니다.

    예를들면 strcpy_s

    1
  • minarai
    2k
    2019-07-25 10:02:39

    Keloper245  크기를 지정하면 \0을 따로 붙혀줘야 한다는 이야기이군요

    저는 자연히 맨 뒤에 붙는줄알고있었네요;;



    이뉴 이쪽 현장 코딩룰이라서 쓰고있었습니다.

    strcpy_s에 대해서는 개인적으로 공부 해보겠습니다

    감사합니다.



    0
  • 인그니야
    497
    2019-07-25 10:11:01 작성 2019-07-25 10:12:05 수정됨

    으아....답글 넘오래 쓰다가...로그인풀려버려서 글 다 날아갔네요....

    다시 간단히 말해보자면, "testData            "는 문자열 길이가 20자이고, 널문자까지 하면 총 21자입니다.

    그러므로 memcpy( str.data1, "testData            ", 20 ); 이후 구조체에 저장된 데이터를 가정해보면,

    str.data = "testData            "

        .data2 = " \0"

        .data3 = " \0"

        .data4 = " \0"

        .data5 = " \0"
    입겁니다.

    그러므로 strlen(str.data)는 str.data[0]~str.data2[0]까지 21일 것이고 sizeof(str.data)는 20일겁니다(왜 그런지는 알거라 생각합니다.).

    이후, memcpy( str.data2, "testData2           ", 20 );하고 나서 구조체에 저장된 데이터를 가정해본다면, 

    str.data = "testData            "

        .data2 = "testData2           "

        .data3 = " \0"

        .data4 = " \0"

        .data5 = " \0"

    일겁니다.

    이 때, strlen(str.data)는 str.data[0]~str.data3[0]까지 41이고, sizeof(str.data)는 여전히 20일겁니다.

    그러므로 trim()함수 안 temp_s1은 "testData            testData2            \0"이고, 앞뒤 공백이 제거된 temp_s2는 "testData            testData2\0"가 될겁니다.

    이게 바로 문제 현상의 원인일 겁니다.

    윗 분들 말씀처럼, 그냥 숫자 데이터들은 mem함수 사용해도, 문자열 관련해서는 문자열함수 쓰는 걸 권장합니다.




    0
  • minarai
    2k
    2019-07-25 10:14:16
    0
  • 독거소년
    2k
    2019-07-25 13:38:06
    0
  • 재현아빠
    1k
    2019-07-25 14:44:01

    원하시는 답을 찾으셨나요?

    질문은 Q&A로..

    0
  • minarai
    2k
    2019-07-25 15:38:06

    재현아빠 

    댓글달아주신 링크들로 답을 찾긴 했습니다.

    질문게시판에 올렸어야했는데 잘못올려버렸네요...

    0
  • 재현아빠
    1k
    2019-07-25 15:47:49
    그럴 수도 있죠. 저는 그냥 리마인드차원에서..ㅋㅋㅋ 혹시 기분나쁘셨다면 죄송합니다.
    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.