밸브라인드를 사용하여 메모리 누수를 찾는 방법
볼라인드를 사용하여 프로그램 메모리 누수를 판별하려면 어떻게 해야 합니까?
누가 도와주셔서 절차를 진행하기 위한 절차를 설명해 주시겠습니까?
, Ubuntu 10.04를 .a.c
Valgrind 실행 방법
OP를 모욕하는 것이 아니라, 아직 Linux를 처음 사용하는 사용자를 위해 Valgrind를 시스템에 설치해야 할 수도 있습니다.
sudo apt install valgrind # Ubuntu, Debian, etc.
sudo yum install valgrind # RHEL, CentOS, Fedora, etc.
sudo pacman -Syu valgrind # Arch, Manjaro, Garuda, etc
Valgrind는 C/C++ 코드에 쉽게 사용할 수 있지만 올바르게 구성되면 다른 언어에도 사용할 수 있습니다(Python에 대해서는 이 항목을 참조하십시오).
Valgrind를 실행하려면 실행 파일을 인수로 전달합니다(모든 매개 변수와 함께 프로그램에).
valgrind --leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--verbose \
--log-file=valgrind-out.txt \
./executable exampleParam1
이 플래그는 요약하면 다음과 같습니다.
--leak-check=full
"하게 표시됩니다 : "각각의 누출이 됩니다."--show-leak-kinds=all
"에 "possible, 'full'은 'full', 'interactive, possible, reachable'로 되어 있습니다.--track-origins=yes
속도보다 유용한 출력을 선호합니다.초기화되지 않은 값의 기원을 추적하여 메모리 오류에 매우 유용할 수 있습니다.발그린드.--verbose
. 프로그램의 비정상적인 동작을 알려줄 수 있습니다.좀 더 장황하게 하기 위해 반복하세요.--log-file
파일에 씁니다.출력이 터미널 공간을 초과할 때 유용합니다.
마지막으로 다음과 같은 Valgrind 보고서가 표시됩니다.
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 636 allocs, 636 frees, 25,393 bytes allocated
All heap blocks were freed -- no leaks are possible
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
누수가 있는데, 어디요?
그래서, 넌 기억이 새고 발그린드는 의미있는 말을 하지 않아아마도 다음과 같은 것이 있을 것이다.
5 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x40053E: main (in /home/Peri461/Documents/executable)
제가 작성한 C코드도 함께 보겠습니다.
#include <stdlib.h>
int main() {
char* string = malloc(5 * sizeof(char)); //LEAK: not freed!
return 0;
}
되었습니다.떻게 ???에는, 「이러다」라고 써 .main
★★★★★★★★★★★★★★★★★」malloc
더 큰 프로그램에서는 추적하는 것이 매우 번거롭습니다.이는 실행 파일이 컴파일된 방식 때문입니다.실제로 무엇이 잘못되었는지 자세히 알 수 있습니다.디버깅 플래그를 사용하여 프로그램을 다시 컴파일합니다(사용 중).gcc
: 기기) :
gcc -o executable -std=c11 -Wall main.c # suppose it was this at first
gcc -o executable -std=c11 -Wall -ggdb3 main.c # add -ggdb3 to it
이 디버깅 빌드에서 Valgrind는 유출된 메모리를 할당하는 정확한 코드 행을 가리킵니다.(문구가 중요합니다.누출된 위치가 정확하지 않을 수 있지만 유출된 내용이 중요할 수 있습니다.트레이스를 사용하면 장소를 찾을 수 있습니다).
5 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x40053E: main (main.c:4)
메모리 누전 및 오류 디버깅 기술
www.cplusplus.com을 이용하세요!C/C++ 함수에 대한 훌륭한 설명서가 있습니다.
메모리 누수에 관한 일반적인 조언:
동적으로 할당된 메모리가 실제로 해방되는지 확인합니다.
메모리를 할당하지 말고 포인터를 할당하는 것을 잊지 마십시오.
오래된 메모리가 해방되지 않는 한 포인터를 새 포인터로 덮어쓰지 마십시오.
메모리 오류에 대한 일반적인 조언:
자신의 주소나 인덱스에 액세스 해 기입할 수 있습니다.누출과 . 이치노
IndexOutOfBoundsException
유형 문제메모리를 해제한 후에는 메모리에 액세스하거나 메모리에 쓰지 마십시오.
IDE가 아직 닫힘 괄호를 입력하지 않은 것을 발견하는 것처럼 누출/오류가 서로 연결될 수 있습니다.하나의 문제를 해결하면 다른 문제를 해결할 수 있습니다.따라서, 적절한 원인으로 생각되는 문제를 찾아, 다음의 몇개의 아이디어를 적용해 주세요.
메모리 에러가 있는 「해당」코드에 의존하거나 의존하는 코드의 함수를 일람표시합니다.프로그램 실행을 추적합니다(아마도
gdb
사전 조건/사후 조건 오류를 찾습니다.이 아이디어는 할당된 메모리의 수명에 초점을 맞추면서 프로그램 실행을 추적하는 것입니다.코드의 「불법」블럭을 코멘트 아웃 합니다(합리적인 범위내에서 코드를 컴파일 할 수 있습니다).발그린드 오류가 사라지면 어디 있는지 알게 될 거야
다른 모든 것이 실패하면 찾아보십시오.발그린드도 문서를 가지고 있어요!
일반적인 누출 및 오류의 개요
포인트에 주의사항
60 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C2BB78: realloc (vg_replace_malloc.c:785)
by 0x4005E4: resizeArray (main.c:12)
by 0x40062E: main (main.c:19)
그리고 코드:
#include <stdlib.h>
#include <stdint.h>
struct _List {
int32_t* data;
int32_t length;
};
typedef struct _List List;
List* resizeArray(List* array) {
int32_t* dPtr = array->data;
dPtr = realloc(dPtr, 15 * sizeof(int32_t)); //doesn't update array->data
return array;
}
int main() {
List* array = calloc(1, sizeof(List));
array->data = calloc(10, sizeof(int32_t));
array = resizeArray(array);
free(array->data);
free(array);
return 0;
}
조교로서 나는 이런 실수를 자주 봐왔다.학생은 로컬 변수를 사용하고 원래 포인터를 업데이트하지 않습니다.는, 「이러다」, 「」라고 하는 입니다.realloc
는 할당된 메모리를 다른 곳으로 이동시켜 포인터의 위치를 변경할 수 있습니다.그리고 나서 우리는 떠난다.resizeArray
array->data
츠미야
잘못된 쓰기
1 errors in context 1 of 1:
Invalid write of size 1
at 0x4005CA: main (main.c:10)
Address 0x51f905a is 0 bytes after a block of size 26 alloc'd
at 0x4C2B975: calloc (vg_replace_malloc.c:711)
by 0x400593: main (main.c:5)
그리고 코드:
#include <stdlib.h>
#include <stdint.h>
int main() {
char* alphabet = calloc(26, sizeof(char));
for(uint8_t i = 0; i < 26; i++) {
*(alphabet + i) = 'A' + i;
}
*(alphabet + 26) = '\0'; //null-terminate the string?
free(alphabet);
return 0;
}
발그린드은 [ [0,25]로 색인화됩니다.*(alphabet + 26)
을 사용하다범위를 벗어납니다.무효 기입을 실시하는 것은, 오프 바이 원 에러에 의한 결과입니다.할당 조작의 좌측을 확인합니다.
잘못된 읽기
1 errors in context 1 of 1:
Invalid read of size 1
at 0x400602: main (main.c:9)
Address 0x51f90ba is 0 bytes after a block of size 26 alloc'd
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x4005E1: main (main.c:6)
그리고 코드:
#include <stdlib.h>
#include <stdint.h>
int main() {
char* destination = calloc(27, sizeof(char));
char* source = malloc(26 * sizeof(char));
for(uint8_t i = 0; i < 27; i++) {
*(destination + i) = *(source + i); //Look at the last iteration.
}
free(destination);
free(source);
return 0;
}
발그린드 」 「 」
*(destination + 26) = *(source + 26);
.하지만,*(source + 26)
유효하지 않은 쓰기와 마찬가지로 다시 범위를 벗어납니다.잘못된 읽기 또한 하나씩의 오류로 인해 발생하는 일반적인 결과입니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
오픈 소스(U/Dys) 토피아
누수가 언제 내 것인지 어떻게 알아?다른 사람의 코드를 사용할 때 유출된 정보를 찾으려면 어떻게 해야 합니까?제 것이 아닌 누수를 발견했는데 어떻게 해야 하나요?모두 정당한 질문입니다.먼저, 두 종류의 일반적인 만남을 보여주는 두 가지 실제 사례입니다.
Janson: JSON 라이브러리
#include <jansson.h>
#include <stdio.h>
int main() {
char* string = "{ \"key\": \"value\" }";
json_error_t error;
json_t* root = json_loads(string, 0, &error); //obtaining a pointer
json_t* value = json_object_get(root, "key"); //obtaining a pointer
printf("\"%s\" is the value field.\n", json_string_value(value)); //use value
json_decref(value); //Do I free this pointer?
json_decref(root); //What about this one? Does the order matter?
return 0;
}
이치노JSON 문자열을 읽고 해석합니다.작성에서는 라이브러리 콜을 사용하여 구문 분석을 수행합니다.JSON은 자신의 중첩된 구조를 포함할 수 있기 때문에 필요한 할당을 동적으로 수행합니다.그렇다고 해서 우리가decref
또는 모든 기능에서 우리에게 주어진 메모리를 해방시킵니다.유효하지 않은 읽기입니다.이러한 오류는 제거하면 사라집니다.decref
은 line line linevalue
.
??value
Jansson API "Janson API"입니다.위해 합니다. 은 단지 Janson에게만 . 을 사용법decref
JSON 구조는 서로 독립적입니다.여기서의 교훈은 매뉴얼을 읽는 것입니다.정말로.이해하기 어려울 때도 있지만 왜 이런 일이 일어나는지 말해주고 있어요.대신 이 메모리 오류에 대한 기존 질문이 있습니다.
SDL: 그래픽스 및 게임 라이브러리
#include "SDL2/SDL.h"
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
SDL_Quit();
return 0;
}
이 코드가 뭐가 문제죠?최대 212KiB의 메모리가 계속 새고 있습니다.잠시 생각해 보세요.SDL을 켜고 끕니다.정답?아무 문제 없어요.
처음에는 이상하게 들릴 수도 있어요.사실 그래픽은 복잡하기 때문에 표준 라이브러리의 일부로 일부 누수를 받아들일 필요가 있습니다.여기서의 교훈은 모든 메모리 누설을 잠재울 필요는 없다는 것입니다.때로는 누출을 억제할 필요가 있습니다.왜냐하면 누출은 어쩔 수 없는 문제이기 때문입니다.(이것은 당신의 누출을 무시하는 나의 허가가 아닙니다!)
공허에 대한 대답
누가 언언 제인 인? ???
99%의 비율
다른 사람의 코드를 사용할 때 유출된 정보를 찾으려면 어떻게 해야 합니까?
아마 다른 누군가가 이미 발견했을 거예요.구글 ★★★★★★★★★★★★★★!실패하면 위에서 알려드린 스킬을 사용하세요.이것이 실패하여 API 콜이 거의 표시되지 않고 자신의 스택트레이스가 거의 표시되지 않는 경우 다음 질문을 참조하십시오.
제 것이 아닌 누수를 발견했는데 어떻게 해야 하나요?
네! 대부분의 API에는 버그나 문제를 보고하는 방법이 있습니다. 을 되돌려 !프로젝트에서 사용 중인 도구를 다시 사용할 수 있습니다.
상세 정보
이렇게 오래 있어줘서 고마워요.이 답변에 도달하는 폭넓은 사람들을 배려하려고 노력했으므로, 당신이 뭔가를 배웠기를 바랍니다.도중에 몇 가지 질문을 해 주셨으면 합니다.C의 메모리 할당기는 어떻게 작동합니까?실제로 메모리 누전과 메모리 오류란 무엇입니까?세그먼트 폴트와는 어떻게 다릅니까?발그린드는 어떻게 작동하나요?이 중 하나라도 가지고 계신 분은 꼭 궁금하신 점을 알려주시기 바랍니다.
이것을 시험해 보세요.
valgrind --leak-check=full -v ./your_program
는 한 valgrind 설치되면 이것은 당신의 프로그램을 통해고 무슨 일인지 말할 것이다.Valgrind가 설치되어 있는 한 프로그램을 통해 무엇이 문제인지 알려줍니다.그것은 당신 포인터의 유출이 대략적인 곳을 줄 수 있다.누수가 발견될 수 있는 대략적인 장소와 힌트를 줄 수 있습니다.만약 당신이 segfault'ing,segfault'를하고 있다면,실행해 보세요를 통해 실행해 보십시오.gdb
.
다음과 같이 .bashrc 파일에 별칭을 생성할 수 있습니다.
alias vg='valgrind --leak-check=full -v --track-origins=yes --log-file=vg_logfile.out'
메모리 누수를 체크하고 싶을 때는 언제든지 간단하게 체크할 수 있습니다.
vg ./<name of your executable> <command line parameters to your executable>
그러면 현재 디렉토리에 Valgrind 로그 파일이 생성됩니다.
실행할 수 있습니다.
valgrind --leak-check=full --log-file="logfile.out" -v [your_program(and its arguments)]
언급URL : https://stackoverflow.com/questions/5134891/how-do-i-use-valgrind-to-find-memory-leaks
'programing' 카테고리의 다른 글
"triggerScroll" 이벤트를 트리거하는 것은 무엇입니까? (0) | 2022.06.30 |
---|---|
마운트된 Vue 인스턴스의 속성을 업데이트하는 방법 (0) | 2022.06.30 |
VueJ 핫 새로고침이 느리다 (0) | 2022.06.30 |
Vue js : Chrome에서 저장된 암호를 변경할 수 없습니다. (0) | 2022.06.30 |
Java 리플렉션 퍼포먼스 (0) | 2022.06.30 |