이미 해제되었을 수있는 포인터를 해제하면 문제가 발생하며 은 사용중인 공간을 모릅니다에는 가장 최근에 할당 된 공간에 대한 포인터가 없습니다 (일반적으로) 그래서 당신은 정확하게 기억을 풀 수 없습니다. main()
에서, 당신은 :
char **images_filenames;
[...]
if ((images_filenames = ((char**) malloc(10 * sizeof (char*)))) == NULL) {
[...]
if (readInputFile(fpin, images_filenames) == -1) {
[...]
deallocate2D(images_filenames, num_lines);
당신은 10 문자 포인터를 할당 한 다음 readInputFile()
기능에 해당 배열을 전달합니다. 이 함수에는 배열을 재 할당하는 코드가 있지만 주 프로그램이 새 주소가 무엇인지 알 수있는 방법을 제공하지 않았습니다. 당신이하는 일은 수정하고자하는 것이 무엇이든간에 포인터를 전달하거나 함수가 수정 된 값을 반환하도록하는 것입니다 (또는 매개 변수 대신 전역 변수를 사용하는 것과 같은 sordid 사례에 의존합니다).하지만 그렇게해서는 안됩니다).
그래서, 당신이 필요합니다
if (readInputFile(fpin, &images_filenames) == -1) {
그리고 readInputFile()
기능에
, 당신은 변화의 전체 많이 필요 - 트리플 포인터 인수를 다루는 큰 하나, 다음 코딩 문제의 다양한 :
int readInputFile(FILE *fp, char ***ppp_files)
{
num_lines = 0;
int s = 10;
char line[MAX_LENGTH];
char **file_images = *ppp_files;
char **final_filenames;
업데이트
: 나는이 단순히 선언하지 NUM_LINES를 초기화하는 것을주의하지 않았다. 따라서 num_lines는 일종의 전역 변수 여야합니다 ... 아래 주석은이를 고려하여 조정해야합니다.
지금까지 변경 사항은 (거의) 사소한 것입니다. 우리는 'char **'에 대한 포인터를 얻습니다. 따라서 트리플 포인터 인수. 다음 코드를 단순화하려면 이전 이름 (file_images
) 아래에서 매개 변수의 로컬 복사본을 만들고 인수가 가리키는 값으로 초기화합니다. 다음 코드는 file_images
으로 계속 작동합니다. 리턴하기 전에 인수가 갱신되었는지 확인하십시오.
제외
...
은 당신의 10 = '가정하지만, 정말, 당신은 주요 기능이 많은 행이 얼마나 당신에게 있어야합니다. 그것은 10 개의 행을 할당했지만,주의 깊은 조사 없이는 명확하지 않습니다. main()
프로그램에 사전 할당 된 행 수 (함수에 대한 추가 인수)가 있어야합니다.또한 main()
프로그램이 알 수 없기 때문에 배열에있는 행의 수를 deallocate2D()
함수가 알 수 없다는 문제가 있습니다. 코드가 어떻게 컴파일되는지는 명확하지 않습니다. 로컬 변수는 num_lines
입니다. 그러나 선언이없는 변수 num_lines
이 main()
에 있습니다. 지역 변수는 모든 전역 변수를 마스킹합니다.
while (fgets(line, sizeof line, fp) != NULL) {
if (line[0] != '\n') {
if (num_lines >= s) {
s += 100;
많은 수의 행을 추가하는 것이 좋습니다. 재 할당 비용을 '상환합니다'.
if ((file_images = (char**) realloc(file_images, s * sizeof (char*))) == NULL)
사용하는 기술에 특정 문제가 있습니다. 순수 코드 스타일 : 라인이 포함 된 할당과 if
를 포함하고 너무 길어질 경우, 조건 전에 할당을 분할 :
file_images = (char**) realloc(file_images, s * sizeof (char*));
if (file_images == NULL)
을 이제 막 미묘한 버그 왼쪽이있다. realloc()
이 실패 할 경우 ...
file_images
의 값이 null이기 때문에 메모리를 유출 했으므로 가리키는 데 사용할 방법이 없습니다. 쓰기 절대로 :
x = realloc(x, size);
그것은 실패의 메모리 누수! 따라서 다음이 필요합니다.
char **new_space = realloc(file_images, s * sizeof (char*));
if (new_space == NULL)
{
printf("Error reallocating space for 2d array: %s\n",
strerror(errno));
*ppp_files = file_images;
return -1;
}
}
일반적으로 오류 메시지는 stderr
에 인쇄되어야합니다. 나는 이것을 고치지 않았다.
주 프로그램의 변수에 마지막 (null이 아닌) 값인 file_images
을 신중하게 복사했음을 유의하십시오. 크기를 변경하거나 (다른 인터페이스 변경) 동일한 작업을 수행하거나 배열을 캡슐화하는 구조 (크기와 포인터를 기본 구조로 사용하는 것이 적절할 수 있습니다.
if ((file_images[num_lines] = malloc(MAX_LENGTH * sizeof (char))) == NULL)
{
printf("Error allocating space for 2d array: %s\n", strerror(errno));
return -1;
}
이 오류를 반환하려면 *ppp_files = file_images;
을 설정해야합니다.
strncpy(file_images[num_lines], line, MAX_LENGTH);
if (file_images[num_lines] == NULL) {
printf("Strncpy failed: %s\n", strerror(errno));
return -1;
}
이 테스트는 이상합니다. file_images[num_lines]
은 null이 아니며 strncpy()
은 변경되지 않습니다. 테스트 및 오류 처리가 필요하지 않습니다. OK
printf("name of file %d is: %s \n", num_lines, file_images[num_lines]);
num_lines++;
}
}
printf("Num_lines: %d\n",num_lines);
...
//realloc to number of lines in the file, to avoid wasting memory
좋은 터치. 간신히 가치가 있습니다. 64 비트 컴퓨터에서도 최대 1Kb 미만의 전력을 낭비하고 있습니다. 그러나, 깔끔하게되는 것에 해로움 - 좋은.
if ((final_filenames = realloc(file_images, num_lines * sizeof (char*))) == NULL) {
printf("Error reallocating space for 2d array: %s\n", strerror(errno));
return -1;
다시 돌아 가기 전에 *ppp_files = file_images;
을 설정해야합니다.
} else {
file_images = final_filenames;
이 내용은 main()
프로그램의 값에는 영향을주지 않습니다. 다시 *ppp_files = file_images;
이어야합니다.
deallocate2D(final_filenames, num_lines);
신중히 할당 된 공간을 모두 할당 해제 하시겠습니까? 결국 당신은 그것을 사용하지 않을 것입니까? 위의 할당은 포인터 값을 복사 한 것입니다. 그것은 메모리의 복사본을 만들지 않았다 ...
이 코멘트는 잘못되었습니다. 성공적인 반환시 메모리는 이미 할당이 해제되었습니다.
Lemme 추측 - 편집을 위해 'vim'또는 다른 'vi'파생물을 사용하지 마십시오. 열 1에 함수의 여는 중괄호가있는 사용자는 ']]
'또는 '[[
'을 사용하여 파일을 통해 다음 또는 이전 함수의 시작으로 앞뒤로 이동할 수 있기 때문에. 작동하지 않는 곳에서 코드 작업을하는 것은 불쾌한 일입니다.
글쎄, 시작 진단 ... 여기에 파일 이름 배열을 전달하는 구조를 사용하는 작업 코드가 있습니다. 구조 밖으로 복사 된 로컬 변수를 사용하여 readInputFile()
함수의 본문을 그대로두고 구조가 항상 올바르게 업데이트되도록했습니다.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
enum { MAX_LENGTH = 512 };
typedef struct FileNameArray
{
size_t nfiles; /* Number of file names allocated and in use */
size_t maxfiles; /* Number of entries allocated in array */
char **files; /* Array of file names */
} FileNameArray;
static void deallocate2D(FileNameArray *names)
{
for (size_t i = 0; i < names->nfiles; i++)
free(names->files[i]);
free(names->files);
names->nfiles = 0;
names->files = 0;
names->maxfiles = 0;
}
static int readInputFile(FILE *fp, FileNameArray *names)
{
int num_lines = names->nfiles;
int max_lines = names->maxfiles;
char **file_names = names->files;
char line[MAX_LENGTH];
char **final_filenames;
while (fgets(line, sizeof line, fp) != NULL)
{
if (line[0] != '\n')
{
/* Remove newline from end of file name */
char *nl = strchr(line, '\n');
if (nl != 0)
*nl = '\0';
if (num_lines >= max_lines)
{
max_lines += 100;
char **space = realloc(file_names, max_lines * sizeof (char*));
if (space == NULL)
{
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = max_lines;
names->files = space;
file_names = space;
}
if ((file_names[num_lines] = malloc(strlen(line) + 1)) == NULL)
{
fprintf(stderr, "Error allocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->nfiles++;
strcpy(file_names[num_lines], line);
printf("name of file %d is: %s \n", num_lines, file_names[num_lines]);
num_lines++;
}
}
printf("Num_lines: %d\n", num_lines);
//realloc to number of lines in the file, to avoid wasting memory
if ((final_filenames = realloc(file_names, num_lines * sizeof (char*))) == NULL)
{
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = num_lines;
names->files = final_filenames;
return 0;
}
int main(int argc, char *argv[])
{
FileNameArray names = { 0, 0, 0 };
//check parameters
if (argc < 4)
{
fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
argv[0]);
return -1;
}
printf("Opening input file [%s]\n", argv[1]);
FILE *fpin = fopen(argv[1], "r");
if (fpin == NULL) {
fprintf(stderr, "Could not open input file %s (%s)\n",
argv[1], strerror(errno));
return -1;
}
if ((names.files = malloc(10 * sizeof (char*))) == NULL)
{
fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
strerror(errno));
return -1;
}
names.maxfiles = 10;
if (readInputFile(fpin, &names) == -1)
{
fprintf(stderr, "Error reading image filenames from input\n");
return -1;
}
fclose(fpin);
printf("###########\n");
deallocate2D(&names);
printf("Done!\n");
return 0;
}
와우, 이제는 분석입니다! 귀하의 노력에 감사 드리며 C 컴파일러를 사용하자 마자 귀하의 제안을 이해하고 적용하려고 노력할 것입니다. 그리고 예, 저는 vim이나 vi를 사용하지 않습니다. Netbeans 나 Geany와 같은 IDE를 사용합니다. 내가 계속 게시하겠습니다. :) – neverMind
@neverMind : 작업 코드에서 메모리 할당 코드를 함수 'int addFileName (FileNameArray * names, const char * line);'과 같은 메소드를 호출하고'readInputFile()'내에서 그것을 호출했다. 그러면 입력 코드에 혼란이 줄어들 것입니다. 그리고'main()'에는 사전 할당이 없습니다. 이 함수는 단순히 처음부터 할당을 처리합니다. –