2012-01-18 3 views
4

처음에는 C 언어에 익숙하지 않았으므로 여기에 근본적인 오해가있을 것입니다. 이와 같은 감안할 코드 :특정 크기의 문자 배열 Malloc 대 문자 배열

int main() 
{ 
    char ack[100]; 
    char *bar; 
    bar = malloc(100); 
    strncpy(ack, "testing", 7);  
    bar = "testing"; 

    return 0; 
} 

ack GDB에 의해 조사 다음과 같습니다

(gdb) p ack 
$1 = "testing\000\360WV\000\000\000\000\000\277\000\000\000\000\000\000  
'\000'\000\220\[email protected]",<repeats 13 times>, "\003\[email protected]", '\000' <repeats 13 times>  
"\325,\[email protected]\000\000\000\000\000H\214\246\367\377\177\000\000\220\[email protected]", 
'\000' <repeats 13 times>,  "P\[email protected]\000\000\000\000\000\360\342\377\377"` 

이것은 내가 ack을 초기화하는 방법을 나에게 주어진에 의미가 있습니다.

(gdb) p bar 
$2 = 0x40066c "testing" 

내가 스토리지의 동일한 금액을 할당 (내가 아는까지로) 내가 ack을위한 공간을 요청했을 때 그랬던 것처럼하지만 malloc을 가지고 있지 않습니다 내가 확실히하지 않는 것은 bar이 보이는 이유 여분의 쓰레기. 알다시피, malloc은 어떤 종류의 데이터 초기화도하지 않기 때문에 다소 혼란 스럽습니다. 그 이유는 내가 strstr을 가지고 겪었던 문제이다. 기본적으로 파일 (fgets)에서 데이터를 읽을 때 특정 크기의 char 배열로 strstr()이 실패합니다 (여분의 정크가 있다고 가정하고 있음). 포인터로 작업하고 malloc 된 메모리는 정상적으로 작동했습니다. 어쨌든 몇 가지 구체적인 질문이 있습니다.

  1. 이 malloc'd 변수의 동작이 예상됩니까? 여기에 최적화가 진행 중입니까 (gcc로 컴파일되었지만 최적화가 수행되지 않았습니까?) 아니면 gdb가 모든 것을 보여주지 않습니까? 해당 변수와 관련된 "정크"가 있어야합니까?

  2. malloc을 올바르게 사용하고 있습니까? 내가 요청한 모든 메모리를 초기화해야합니까? 그렇다면 어떻게?

고맙습니다!

편집 응답 모든 사람에게

감사합니다! 나는 당신에게서 모든 것을 아주 많이 배웠고 많은 도움을 받았습니다. 이제 위의 코드와 fgets() 및 strstr()에 대한 문제를 확인합니다.

+0

메모리가 할당되면 메모리가 Null로 채워지지 않습니다. 그걸 사용하려면 memset (..) – Adrian

+2

@ 애드 리안, 아니, 아니. 이것은'C'입니다. 'malloc()'을 사용하지 말고'C '에 대해 새로운 것을 가르쳐주지 마라. –

+0

@DanFego 나는 또한 나는 하하를 추측하고있다. 나는 항상 mallocs를 캐스팅했습니다. 정보 주셔서 감사합니다. 내 의견을 편집했습니다! – Adrian

답변

10
bar = "testing"; 

그것이 더 이상 점하여 malloc 'D 배열bar 문자열 "testing" 채 정적 버퍼 가리 포인터, 즉를 재 - 할당하지 않는다. 이것은 memory leak입니다.

malloc 'D 버퍼에 문자열을 얻을 당신이 ack와 함께했던 것처럼, strcpy, strncpy 또는 memcpy 사용합니다.

+3

여분의 +1은 메모리 누수임을 나타냅니다. – cdeszaq

2

리터럴과 더 이상 (유출) malloc 에드 메모리에 문자열 bar 점을하게

bar = "testing"; 

을 할당 할 때 (실수)를 malloc 에드 메모리를 던져 때문입니다.

+0

'malloc' 메모리를 버리는 것이 아니라'forget about '이라고 말하고 싶습니다. – cdeszaq

+0

'throw away'는 의도를 암시하기 때문에 잊어 버릴 점입니다. 반면에, '잊어 버리라'는 기억이 누출 될 정도로 극적으로 들리지는 않습니다. 나는 타협했다. –

+0

완벽한! 우리는 또한 "잃어", "누출", "드롭", "무시"및 "우주 쓰레기로 투기"를 받아 들였습니다. – cdeszaq

-1

C 문자열은 null 종결 자 (ascii 문자 값이 0)이므로 C 문자열 "testing"은 실제로 종결자를 포함하여 8 바이트 길이입니다.

원래 값을 인쇄하면 종결 자에 도달하면 인쇄가 중지됩니다.

처음 7 자만 복사했기 때문에 두 번째 값을 인쇄 할 때 이전에 있던 가비지 데이터에서 0에 도달 할 때까지 정크 인쇄가 계속됩니다.

+0

어쩌면 그것은 Daniel의 설명이었을 것입니다. 기술적으로는 사실이지만, 나는 downvote를받을 자격이 없다고 생각합니다. –

0

몇 가지 사항을 알려 드리겠습니다.

먼저, "NULL"로 끝내지 않았기 때문에 ack에 "테스트"후 가비지가 인쇄됩니다. C에서 모든 문자열은 NULL로 종료되어야하며, 즉 \0으로 끝나야합니다. 당신은 길이 8 (strlen("testing") + 1) or just using의 strcpy()와 strncpy()를 호출하여 여기에이 문제를 해결 할 수 있습니다. 그것은 char에 대한 포인터이기 때문에

둘째, bargdb 다른 모습, ack 직선 업 char 배열된다. gdb 당신을 보여줍니다 bar에 대한 포인터 값이지만, 가능한 한 포인터의 반대편에있는 내용을 보여줌으로써 사용자에게 유리합니다. 그리고 bar = "testing;"을 수행하면 bar이 가리키는 부분을 다시 할당합니다. 메모리에 "testing"을 포함하는 문자 배열. 문자열 리터럴을 사용하면 자동으로 끝에 \0 문자가 있으므로 NULL로 끝나고 그러므로 나중에 쓰레기를 가지지 않습니다.