0

でログ エントリを含むディレクトリを作成しようとしていますmkstemp。しかし、私の理解では、文字列定数を に渡してはいけませんmkstemp。文字列にメモリを割り当てsnprintf、動作すると思っていた出力をフォーマットするために使用しますが、mkstempEINVAL に errno を設定する負の値を返します。

ただし、Linuxのマニュアルには、次のmkstempように明確に記載されています。

EINVAL mkstemp() および mkostemp() の場合: template の最後の 6 文字が XXXXXX ではありませんでした。現在、テンプレートは変更されていません。

さらにmkstemp、動的文字列を変更することはありません。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LOG_DIR "/tmp"

int main(int argc, char **argv) {
  char *fname;
  FILE *fp;

  if(argc != 3) {
    fprintf(stderr, "Usage: %s <msg> <severity>\n", argv[0]);
    return 0;
  }

  int length = snprintf(NULL, 0, "%s/log_entry.XXXXXX", LOG_DIR); // snprintf returns the required length for my string
  if(length < 0) {
    perror("snprintf failed");
    return 1;
  }
  fname = malloc(sizeof(char) * length); // allocate memory for fname based on the return value of snprintf
  snprintf(fname, length, "%s/log_entry.XXXXXX", LOG_DIR); // send formatted output into fname

  int fd = mkstemp(fname); // this returns -1 and errno is set to 22
  if(fd < 0) {
    perror("failed to create entry file");
    return 1;
  }
  fp = fdopen(fd, "w");
  if(fp == NULL) {
    perror("failed to open entry file");
    return 1;
  }
  fprintf(fp, "\"%s\" %d ",argv[1], atoi(argv[2]));
  fflush(fp);
  fclose(fp);
  free(fname);
  return 0;
}

このスニペットは両方の Linux マシンでエラーを吐き出しますが、動的に割り当てられた文字列を削除して明示的に設定fnameすると動作します

char fname[] = "/tmp/log_entry.XXXXXX";
4

2 に答える 2

2
fname = malloc(sizeof(char) * length);

次のようにする必要があります。

fname = malloc(sizeof(char) * (length + 1)); 

snprintf(fname, length+1, "%s/log_entry.XXXXXX", LOG_DIR); 

ファイル名を作成します。お使いのバージョンでは、ファイル名が 6 つの 'X' で終わっておらず、mkstemp失敗しました。

于 2015-10-24T13:27:06.923 に答える
1
 fname = malloc(sizeof(char) * length); 

あなたはそれを完全に埋めて、 のためのスペースを残さない'\0'. :ヌルターミネータ用のスペースを確保 -

 fname = malloc(sizeof(char) *(length+1)); 

snprintf次に、長さも に伸ばしlength+1ます。

于 2015-10-24T13:26:59.227 に答える