【问题标题】:Heap in function overlaps function parameter函数中的堆与函数参数重叠
【发布时间】:2021-05-23 11:35:37
【问题描述】:

我编写了一个程序,将输出目录名(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] = '\0';

#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 '\0' */);
        //#endif
        /*sprintf(input_files_fullpath[file_iter], "%s/%s%c",
                  input_dir,
                  input_files_basename[file_iter],
                  '\0');*/

#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函数参数?如果有人能解释一下,我将不胜感激。

【问题讨论】:

  • char *output_files_fullpath[] = {NULL}; output_files_fullpath 有多少个元素?你打算写多少?

标签: c malloc


【解决方案1】:

为什么 malloc 会与 input_dir 函数参数重叠?

因为您的代码无效。数组:

char *output_files_fullpath[] = {NULL};

只有一个元素,但你在 form_fullpath 中用伪代码写出越界:

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 只有 1 个元素,而不是 5 个元素。您可以:

  • 分配更多元素char *output_files_fullpath[20];
  • 例如,使用动态分配在每个循环中动态重新分配output_files_fullpath

注意事项:

  • 您可以使用asprintf,而不是malloc+snprintf。`
  • sprintf(..., "%c", '\0') 毫无意义,会导致在字符串末尾写入 两个 零,我认为这也是一个错误,因为它会导致按字节越界写入内存.删除 '\0'sprintf 总是自己写零终止字符。
  • 更喜欢使用snprintf
  • 我猜,考虑使用较短的变量名? output_files_fullpath在函数中变成input_files_fullpath有点奇怪,它仍然是输出。
  • 考虑将size_t 用于数组迭代器。

【讨论】:

  • 谢谢。我真的离指针数组不太近。你的解释对我很有帮助。我刚刚从指针数组中删除了终止零并使用 snprintf 而不是 sprintf。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
相关资源
最近更新 更多