"내 코드가 작동하지 않는 이유는 무엇입니까?"— 프로그래밍 기술을 배우고 스택 오버플로 커뮤니티에 글을 쓰는 모든 사람에게
6495 단어 beginnerscppprogrammingtutorial
며칠 전 저는 Stack Overflow를 탐색하다가 흥미로운 토론을 우연히 발견했습니다: "Segmentation fault when converting char * to char **" . 저자는 코딩 방법을 배우고 있으며 코드의 문제점을 알고 싶어합니다.
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
char **get_words(char *buffer, char delimiter)
{
printf("buffer = %s\n", buffer);
char **words = malloc(sizeof(char *) * 100);
if (words == NULL) {
printf("Malloc Error\n");
exit(84);
}
for (int i = 0; i < 100; i++) {
words[i] = malloc(sizeof(char) * 100);
if (words[i] == NULL) {
printf("Malloc Error\n");
exit(84);
}
}
int word_count = 0;
int l = 0;
for (int i = 0; buffer[i] != '\0' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '\0';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '\0';
return (words);
}
int main()
{
char *buffer = malloc(sizeof(char) * 100);
buffer = "hello world !\n";
char **words = get_words(buffer, ' ');
printf("words[0]= %s\n", words[0]);
free (buffer);
char **reply = get_words("Second call\n", ' ');
printf("reply[0] = %s\n", reply[0]);
}
Stack Overflow는 이러한 질문으로 가득 차 있습니다. 그리고 지역 전문가들은 구출에 열성적이지 않습니다. 이것은 의미가 있습니다. 숙련된 개발자에게 지루한 실수를 찾기 위해 많은 코드를 살펴보는 것은 그리 재미있는 일이 아닙니다. 이러한 실수는 일반적으로 프로그래밍 언어 지식의 차이에서 발생합니다. 따라서 초보자가 일반적으로 얻는 모든 도움은 프로그래밍 책의 특정 장을 읽거나 문서를 공부하라는 권장 사항입니다.
이것은 전문가가 도움을 꺼리거나 무례하다는 것을 의미하지 않습니다. 그들은 학업과 같은 일을 하는 것에 대해 그다지 흥분하지 않습니다.
하지만 앞에서 언급한 스택 오버플로 질문으로 돌아가 보겠습니다. 질문은 이미 며칠이 지났지만 여전히 답이 없습니다. 거기에서 어떻게 앞으로 나아갈 수 있습니까?
여기에서 정적 분석기가 구조에 올 수 있습니다! 이 도구가 전문가와 초보자 모두에게 유용할 수 있다는 것을 알고 계셨습니까? 정적 분석기는 code review을 수행하고 의심스러운 코드 조각을 보고하는 도구입니다. 정적 분석기는 팀원이 수행한 코드 검토를 대체할 수 없지만 조기에 오류를 찾는 데 도움이 되므로 코드 검토 프로세스에 큰 도움이 될 수 있습니다.
이제 토론에 게시된 코드에 대한 PVS-Studio 분석기의 온라인 버전run을 살펴보겠습니다. 첫 번째 흥미롭고 유용한 경고는 다음과 같습니다. V1031 'malloc' 함수가 선언되지 않았습니다. 이 함수로 또는 이 함수에서 데이터를 전달하는 것이 영향을 받을 수 있습니다.
malloc 함수가 선언된 적이 없기 때문에 실행 흐름이 어떻게 작동할지 명확하지 않습니다. C 프로그래밍 언어에서 함수가 먼저 선언되지 않고 사용되면 이 함수는 int를 반환하는 것으로 간주됩니다. 그러나 이 경우 함수는 포인터를 반환합니다. 이것이 안전하지 않은 이유에 대한 메모를 작성했습니다: "A nice 64-bit error in C" . #include 를 추가하여 이 문제를 해결해 보겠습니다.
이제 analyzer's output이 변경되고 또 다른 심각한 문제가 나타납니다. 43:1: 참고: V773 메모리를 해제하지 않고 '버퍼' 포인터에 값이 두 번 할당되었습니다. 메모리 누수가 가능합니다.
오류는 다음과 같습니다.
char *buffer = malloc(sizeof(char) * 100);
buffer = "hello world !\n";
....
free (buffer);
포인터의 값이 지워집니다. 문자열을 버퍼에 올바르게 복사하려면 strcpy 과 같은 특수 함수를 사용해야 합니다. 코드를 수정합시다.
The correct code :
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
char **get_words(char *buffer, char delimiter)
{
printf("buffer = %s\n", buffer);
char **words = malloc(sizeof(char *) * 100);
if (words == NULL) {
printf("Malloc Error\n");
exit(84);
}
for (int i = 0; i < 100; i++) {
words[i] = malloc(sizeof(char) * 100);
if (words[i] == NULL) {
printf("Malloc Error\n");
exit(84);
}
}
int word_count = 0;
int l = 0;
for (int i = 0; buffer[i] != '\0' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '\0';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '\0';
return (words);
}
int main()
{
char *buffer = malloc(sizeof(char) * 100);
if (buffer == NULL)
exit(84);
strcpy(buffer, "hello world !\n");
char **words = get_words(buffer, ' ');
printf("words[0]= %s\n", words[0]);
free (buffer);
char **reply = get_words("Second call\n", ' ');
printf("reply[0] = %s\n", reply[0]);
}
수정된 코드가 아름답지도 안전하지도 않지만 이제 제대로 작동합니다. 따라서 위에서 보여드린 접근 방식은 코드에서 오류를 찾고 학습 과정에서 도움을 받을 수 있는 좋은 방법이 될 수 있습니다.
추가 리소스:
Static code analysis .
Reference
이 문제에 관하여("내 코드가 작동하지 않는 이유는 무엇입니까?"— 프로그래밍 기술을 배우고 스택 오버플로 커뮤니티에 글을 쓰는 모든 사람에게), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/unicorn_developer/why-doesnt-my-code-work-to-anyone-learning-the-art-of-programming-and-writing-to-the-stack-overflow-community-5b76텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)