【问题标题】:Seg Fault when working with strings C Program / Popen使用字符串 C Program / Popen 时出现 Seg Fault
【发布时间】:2016-06-27 18:08:57
【问题描述】:

我已经为我的问题寻找了将近两天的答案,并尝试了所有建议的解决方案,但均无济于事。 我正在尝试使用我的 C 程序通过 linux 终端访问文件。 我想运行popen() 来执行此操作。

我想在 popen() 中运行的命令是:grep -o %s /usr/share/dict/words

其中%s 是一个变量词,每次迭代都会改变。我尝试过使用指针、数组和替代函数,例如 asprintf() / snprintf()

这是我现在拥有的代码:

char *message = (char *)malloc(500);
strcpy(message, "grep -n");
printf("%s", message);
strcat(message, "hello");
printf("%s", message);
strcat(message, " /usr/share/dict/words"); // SEG FAULT OCCURS HERE
printf("%s", message);

然后我会将它传递给popen。 我也尝试过初始化为:char message[500],这会在同一个地方返回相同的错误。

这是我的完整代码:

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

int main( int argc, char *argv[]){

  char *inputfile;
  int n = 0;
  int shiftamount = 0;

  //Determine amount of arguments
  if(argc == 2){
   inputfile = argv[1];
   }
  else if(argc == 3){
    inputfile = argv[1];
    n = atoi(argv[2]);
    shiftamount =  n * (-1) ;
  }
  else{
    printf("Please enter a proper number of arguments.");
    return -1;
  }

  //OPENS INPUT FILE
  FILE *input = fopen(inputfile, "r");

  if(input == NULL){
    printf("\n FILE NOT FOUND.");
    perror("fopen");
    return -1;
  }

  //RESERVES MEMORY AND GRABS STRING
  fseek(input, 0L, SEEK_END);
  long Tsize = ftell(input);
  rewind(input);

  char *inputtext;
  inputtext = calloc( 1, Tsize+1);



//ERROR CHECKING
  if(!inputtext){
    fclose(input), printf("MEMORY FAILED.");
  }
  if(1!=fread( inputtext, Tsize, 1, input)){
    fclose(input), free(inputtext), printf("READ FAIL.");
  }

  //CREATES DECRYPTED STRING

  char newletter;
  char *newstring;
  int i;

  //WITH GIVEN NUMBER OF SHIFTS

  if(argc == 3){
  newstring = malloc(Tsize + 1);

  for(i=0; i<Tsize; i++){
    newletter = shift(inputtext[i], shiftamount);
    newstring[i] = newletter;
  }
  }

  //WITHOUT GIVEN NUMBER OF SHIFTS
  if(argc == 2){

 char *message = (char *)malloc(500); //SEG FAULT SOMEWHERE HERE?
    // strcpy(message, "grep -n");
    //    printf("%s", message);
    //strcat(message, "hello");
    //    printf("%s", message);
    //    strcat(message, "/usr/share/dict/words");
    //printf("%s", message);

    //    word = strtok(inputtext," ,.-!?\n");

    // int i;


       //for(i=0; i<10; i++){
        //word = strtok(NULL," ,.-!?\n");
        //printf("\n%s", word);
//}
   //  if(( fp = popen(message, "r")) == NULL){
    //perror("No file stream found.");
    //return -1;
    // }

      // else {
      // pclose(fp);

      // printf("FOUND.");
      //        }

  }

  // PUTS DECRYPTED STRING IN NEW FILE

  char copiedname[100];
  strcpy(copiedname, inputfile);
  strcat(copiedname, ".dec");
  FILE *newfile = fopen(copiedname, "w");
  fputs(newstring, newfile);

  //  free(newstring);
  fclose(input);
  fclose(newfile);

  return 0;

}

【问题讨论】:

  • 你介意创建一个MCVE吗?
  • 您是否尝试在调试器中运行以捕捉实际的崩溃?崩溃发生时所涉及的变量的值是多少? message 的长度够吗?
  • 此外,由于您不刷新stdout,因此您无法确定崩溃是否真的发生在您认为发生的地方,您也应该为此使用调试器。或者至少在这些printf 调用中添加一个尾随换行符。
  • 除了调试器的建议,也可以尝试使用valgrind
  • 您是否尝试过使用静态代码分析工具(例如 cppcheck)检查您的代码?

标签: c linux string segmentation-fault malloc


【解决方案1】:

您已将 inputfile 设置为 argv[1],后来您使用 strcat 附加到它。不要这样做。你不拥有 argv。

strcat 函数将源字符串的副本附加到目标字符串,然后返回指向目标字符串的指针。它确实 not “添加两个字符串并返回结果”,这就是您使用它的方式。

【讨论】:

  • 所以我应该 strcpy() argv[1] 到一个新的缓冲区,然后附加“.dec”对吗?
  • 我这样做了,但它没有解决我的分段错误。不过谢谢
  • 是的,你可以这样做,只要你分配的缓冲区足够长,可以包含 argv[1] 加上 ".dec" 加上一个零终止符。
  • @heyjaynell,既然什么都没有改变,为什么不简单地初始化message[] = "grep -n hello /usr/share/dict/words";(或使其成为字符串文字)?
猜你喜欢
  • 2018-06-30
  • 1970-01-01
  • 2015-02-19
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多