函数中的堆与函数参数重叠
Heap in function overlaps function parameter
我编写了一个程序,将输出目录名 (argv[1]
) 与文件名 (char *output_files_basename[]
) 合并:
algo.c:
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "algo.h"
#include "parameters.h"
char *output_files_basename[] = {
"test1",
"test2",
"test3",
"test4",
NULL
};
extern int errno;
int main(int argc, char *argv[]) {
char output_dir[MAX_PATH_LENGTH] = "";
char *output_files_fullpath[] = { NULL };
int ret = 0;
/* check parameters */
if (argc < 2) {
printf("Not enough parameters\n");
printf("Should be:\n");
printf("%s output_dir\n", argv[0]);
return EINVAL;
}
#if DEBUG > 0
printf("Arguments: \n");
printf("output_dir: %s\n", argv[1]);
#endif
strncpy(output_dir, argv[1], MAX_PATH_LENGTH - 1);
output_dir[MAX_PATH_LENGTH - 1] = '[=10=]';
#if DEBUG > 0
printf("output_dir: %s\n", output_dir);
#endif
/* set full input file names */
form_fullpath(output_files_fullpath, output_files_basename, output_dir);
free_fullpath(output_files_fullpath);
return EXIT_SUCCESS;
}
algo.h:
#ifndef ALGO_H
#define ALGO_H
#define DEBUG 1
#define MAX_PATH_LENGTH 256
#endif /* ALGO_H */
parameters.h:
#ifndef PARAMETERS_H
#define PARAMETERS_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include "algo.h"
/* get input_dir and append to input_files_basename => input_files_fullpath */
void form_fullpath(char *input_files_fullpath[], char *input_files_basename[], char *input_dir);
/* free memory */
void free_fullpath(char *input_files_fullpath[]);
#endif /* PARAMETERS_H */
parameters.c:
#include "parameters.h"
extern int errno;
void form_fullpath(char *input_files_fullpath[], char *input_files_basename[], char *input_dir) {
int file_iter = 0;
char *strtmp = NULL;
for (file_iter = 0; input_files_basename[file_iter] != NULL && input_dir != NULL; file_iter++) {
//#ifdef TTT
input_files_fullpath[file_iter] = malloc(sizeof(char) *
(strlen(input_files_basename[file_iter]) +
strlen(input_dir) + 2) /* '/' and '[=13=]' */);
//#endif
/*sprintf(input_files_fullpath[file_iter], "%s/%s%c",
input_dir,
input_files_basename[file_iter],
'[=13=]');*/
#if DEBUG > 0
//printf("file_fullpath[%d]: %s\n", file_iter, input_files_fullpath[file_iter]);
printf("input_files_basename[%d]: %s\n", file_iter, input_files_basename[file_iter]);
printf("%d input_dir: %s\n", file_iter, input_dir);
#endif
}
input_files_fullpath[file_iter] = NULL;
}
void free_fullpath(char *input_files_fullpath[]) {
int file_iter = 0;
for (file_iter = 0; input_files_fullpath[file_iter] != NULL; file_iter++) {
free(input_files_fullpath[file_iter]);
}
}
当我在 form_fullpath
函数中评论 malloc
时,我得到以下输出:
./algo output/
Arguments:
output_dir: output/
output_dir: output/
input_files_basename[0]: test1
0 input_dir: output/
input_files_basename[1]: test2
1 input_dir: output/
input_files_basename[2]: test3
2 input_dir: output/
input_files_basename[3]: test4
3 input_dir: output/
但是当我在 form_fullpath
函数中取消注释 malloc
时,我的输出是这样的:
./algo output/
Arguments:
output_dir: output/
output_dir: output/
input_files_basename[0]: test1
0 input_dir: output/
input_files_basename[1]: test2
1 input_dir: P
input_files_basename[2]: test3
2 input_dir: P
input_files_basename[3]: test4
3 input_dir: P
为什么 malloc
与 input_dir
函数参数重叠?如果有人能解释我,我将不胜感激。
Why malloc overlaps input_dir function parameter?
Because your code is invalid. The array:
char *output_files_fullpath[] = {NULL};
has only one element, yet you write out-of-bounds to it in form_fullpath
, in pseudocode:
int main() {
char *output_files_fullpath[] = {NULL};
form_fullpath(output_files_fullpath, ...)
}
void form_fullpath(char *input_files_fullpath[], ...) {
for (file_iter in 0 1 2 3) {
input_files_fullpath[file_iter] = something
}
}
input_files_fullpath
has only 1 element, not 5. You can:
- Allocate more elements
char *output_files_fullpath[20];
- use dynamic allocation to dynamically re-allocate
output_files_fullpath
each loop, for example.
Notes:
- Instead of
malloc+snprintf
you could use asprintf
.`
- Doing
sprintf(..., "%c", '[=18=]')
is pointless, results in writing two zeros on the end of string and I think this is also a bug as it results in writing to the memory out-of-bounds by byte. Remove that '[=19=]'
. sprintf
always writes zero terminating character by itself anyway.
- Prefer to use
snprintf
.
- I guess, consider using shorter variable names? It's kind of strange that
output_files_fullpath
becomes input_files_fullpath
in function, it's still output.
- Consider using
size_t
for array iterators.
我编写了一个程序,将输出目录名 (argv[1]
) 与文件名 (char *output_files_basename[]
) 合并:
algo.c:
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "algo.h"
#include "parameters.h"
char *output_files_basename[] = {
"test1",
"test2",
"test3",
"test4",
NULL
};
extern int errno;
int main(int argc, char *argv[]) {
char output_dir[MAX_PATH_LENGTH] = "";
char *output_files_fullpath[] = { NULL };
int ret = 0;
/* check parameters */
if (argc < 2) {
printf("Not enough parameters\n");
printf("Should be:\n");
printf("%s output_dir\n", argv[0]);
return EINVAL;
}
#if DEBUG > 0
printf("Arguments: \n");
printf("output_dir: %s\n", argv[1]);
#endif
strncpy(output_dir, argv[1], MAX_PATH_LENGTH - 1);
output_dir[MAX_PATH_LENGTH - 1] = '[=10=]';
#if DEBUG > 0
printf("output_dir: %s\n", output_dir);
#endif
/* set full input file names */
form_fullpath(output_files_fullpath, output_files_basename, output_dir);
free_fullpath(output_files_fullpath);
return EXIT_SUCCESS;
}
algo.h:
#ifndef ALGO_H
#define ALGO_H
#define DEBUG 1
#define MAX_PATH_LENGTH 256
#endif /* ALGO_H */
parameters.h:
#ifndef PARAMETERS_H
#define PARAMETERS_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include "algo.h"
/* get input_dir and append to input_files_basename => input_files_fullpath */
void form_fullpath(char *input_files_fullpath[], char *input_files_basename[], char *input_dir);
/* free memory */
void free_fullpath(char *input_files_fullpath[]);
#endif /* PARAMETERS_H */
parameters.c:
#include "parameters.h"
extern int errno;
void form_fullpath(char *input_files_fullpath[], char *input_files_basename[], char *input_dir) {
int file_iter = 0;
char *strtmp = NULL;
for (file_iter = 0; input_files_basename[file_iter] != NULL && input_dir != NULL; file_iter++) {
//#ifdef TTT
input_files_fullpath[file_iter] = malloc(sizeof(char) *
(strlen(input_files_basename[file_iter]) +
strlen(input_dir) + 2) /* '/' and '[=13=]' */);
//#endif
/*sprintf(input_files_fullpath[file_iter], "%s/%s%c",
input_dir,
input_files_basename[file_iter],
'[=13=]');*/
#if DEBUG > 0
//printf("file_fullpath[%d]: %s\n", file_iter, input_files_fullpath[file_iter]);
printf("input_files_basename[%d]: %s\n", file_iter, input_files_basename[file_iter]);
printf("%d input_dir: %s\n", file_iter, input_dir);
#endif
}
input_files_fullpath[file_iter] = NULL;
}
void free_fullpath(char *input_files_fullpath[]) {
int file_iter = 0;
for (file_iter = 0; input_files_fullpath[file_iter] != NULL; file_iter++) {
free(input_files_fullpath[file_iter]);
}
}
当我在 form_fullpath
函数中评论 malloc
时,我得到以下输出:
./algo output/
Arguments:
output_dir: output/
output_dir: output/
input_files_basename[0]: test1
0 input_dir: output/
input_files_basename[1]: test2
1 input_dir: output/
input_files_basename[2]: test3
2 input_dir: output/
input_files_basename[3]: test4
3 input_dir: output/
但是当我在 form_fullpath
函数中取消注释 malloc
时,我的输出是这样的:
./algo output/
Arguments:
output_dir: output/
output_dir: output/
input_files_basename[0]: test1
0 input_dir: output/
input_files_basename[1]: test2
1 input_dir: P
input_files_basename[2]: test3
2 input_dir: P
input_files_basename[3]: test4
3 input_dir: P
为什么 malloc
与 input_dir
函数参数重叠?如果有人能解释我,我将不胜感激。
Why malloc overlaps input_dir function parameter?
Because your code is invalid. The array:
char *output_files_fullpath[] = {NULL};
has only one element, yet you write out-of-bounds to it in form_fullpath
, in pseudocode:
int main() {
char *output_files_fullpath[] = {NULL};
form_fullpath(output_files_fullpath, ...)
}
void form_fullpath(char *input_files_fullpath[], ...) {
for (file_iter in 0 1 2 3) {
input_files_fullpath[file_iter] = something
}
}
input_files_fullpath
has only 1 element, not 5. You can:
- Allocate more elements
char *output_files_fullpath[20];
- use dynamic allocation to dynamically re-allocate
output_files_fullpath
each loop, for example.
Notes:
- Instead of
malloc+snprintf
you could useasprintf
.` - Doing
sprintf(..., "%c", '[=18=]')
is pointless, results in writing two zeros on the end of string and I think this is also a bug as it results in writing to the memory out-of-bounds by byte. Remove that'[=19=]'
.sprintf
always writes zero terminating character by itself anyway. - Prefer to use
snprintf
. - I guess, consider using shorter variable names? It's kind of strange that
output_files_fullpath
becomesinput_files_fullpath
in function, it's still output. - Consider using
size_t
for array iterators.