繁体   English   中英

连接两个字符串的分段错误

[英]Segmentation fault with concatenation of two strings

我正在尝试构建由 3 个首字母和 3 个最终数字组成的字母数字字符串,并将它们保存在.txt文件中。 我写了这个:

int i = 0,          
    j = 0;     
char name_cpu[8],
     array_numbers_final[8],    
     array_letters[27] = "ABCDEFGHIJKLMNOPQRSTUWXYVZ",
     array_numbers[10] = "123456789";


/* Generator data */
  for(i = 0; i < number_cpu; i++)
  { 
      for(j = 0; j < 3; j++){
      name_cpu[j] = array_letters[rand() % (sizeof(array_letters)-1)];
      array_numbers_final[j] = array_numbers[rand() % (sizeof(array_numbers)-1)];
    }

    strcat(name_cpu, array_numbers_final);
    fprintf(list_cpu, "%s \n", name_cpu);
  }

问题在于,在第一个外部for循环中,它正确打印了一个“AAA000”形式的字符串。 在第二个 for 循环中,它进入分段错误。 谁能告诉我我做错了什么以及在哪里做错了?

编辑:一个最小的可重现示例是:

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

int main (void){

  FILE *list_cpu = NULL;
  int i = 0,
  number_cpu = 3,    
  j = 0;     
  char name_cpu[8] = {0},
  array_numbers_final[8] = {0},    
  array_letters[27] = "ABCDEFGHIJKLMNOPQRSTUWXYVZ",
  array_numbers[10] = "123456789";
        
  list_cpu = fopen("list_cpu.txt", "w");  
        
        
  /* Generator data */
  for(i = 0; i < number_cpu; i++)
  { 
    for(j = 0; j < 3; j++){
      name_cpu[j] = array_letters[rand() % (sizeof(array_letters)-1)];
      array_numbers_final[j] = array_numbers[rand() % (sizeof(array_numbers)-1)];
  }
   strcat(name_cpu, array_numbers_final);
   fprintf(list_cpu, "%s \n", name_cpu);
  }
  fclose(list_cpu);

return(0);
}

如果number_cpu等于 1 它可以工作。 但如果它高于 1,则程序进入分段错误。

回答对 OP 的新编辑

对 OP 的编辑包括初始化变量,以解决原始代码中未定义行为的一些实例,但缓冲区溢出问题仍然存在于以下部分:

/* Generator data */
  for(i = 0; i < number_cpu; i++)
  { 
    for(j = 0; j < 3; j++){
      name_cpu[j] = array_letters[rand() % (sizeof(array_letters)-1)];
      array_numbers_final[j] = array_numbers[rand() % (sizeof(array_numbers)-1)];
  }
   strcat(name_cpu, array_numbers_final);
   fprintf(list_cpu, "%s \n", name_cpu);
  }
  fclose(list_cpu);

其中name_cpu用 8 个字符定义: char name_cpu[8] = {0}

“如果 number_cpu 等于 1 它可以工作。但如果它高于 1,则程序进入分段错误。”...

在外循环的第一次迭代之后,包括一个strcat name_cpulist_cpuchar name_cpu填充有 6 个新字符和\0在剩余位置。 例如:

//example
|S|J|P|Y|E|P|\0|\0|  //

该错误发生在strcat()语句的外部循环的第二次迭代结束时。 内部循环重新填充了name_cpu的前三个位置,例如:

//first three positions changed, the rest remains
|C|B|A|Y|E|P|\0|\0|  // 
 ^ ^ ^ updated values

array_numbers_final的新值发生错误:

|G|H|O|\0|\0|\0|\0|\0|

试图连接到name_cpu ,导致:

|C|B|A|Y|E|P|G|H|O|  //attempt to write to memory not owned
                ^end of buffer

导致缓冲区溢出错误,并可能出现分段错误错误情况。 同样,和以前一样,设计变量以满足程序的潜在需求。 在这种情况下,以下将起作用:

 char name_cpu[100] = {0};
 char array_numbers_final[100] = {0};     

回复原帖
问题在这里:

strcat(name_cpu, array_numbers_final);//undefined behavior.

首先, name_cpu[8]在声明时是未初始化的,也不是在使用前的任何时候初始化的。 因为不能保证内容是什么,所以不一定是字符串。 在任何字符串中使用此变量 function 可以调用未定义的行为

此外,(即使name_cpu是有效字符串)当array_numbers_final连接到name_cpu时,缓冲区将溢出。 在我的测试运行中,我看到了这个:

在此处输入图像描述

解决方法是从用于预期目的的足够大小的初始化缓冲区开始。 例如:

 char name_cpu[100] = {0}
 array_numbers_final[100] = {0},    
 array_letters[27] = "ABCDEFGHIJKLMNOPQRSTUWXYVZ",
 array_numbers[10] = "123456789";

下面的代码示例是使用您提供的示例进行改编,并带有建议的编辑。 阅读在线评论:

int main(void)
{
    int number_cpu = 3;//added - previously not defined in OP
    int i = 0,          
    j = 0;     
    char name_cpu[100] = {0},//resized and initialize
     array_numbers_final[100] = {0},//resized and initialize    
     array_letters[27] = "ABCDEFGHIJKLMNOPQRSTUWXYVZ",
     array_numbers[10] = "123456789";


/* Generator data */
      for(i = 0; i < number_cpu; i++)
      { 
          for(j = 0; j < 3; j++){
          name_cpu[j] = array_letters[rand() % (sizeof(array_letters)-1)];
          array_numbers_final[j] = array_numbers[rand() % (sizeof(array_numbers)-1)];
        }

        strcat(name_cpu, array_numbers_final);
        fprintf(stdout, "%s \n", name_cpu);//to stdout
        //        ^ changed here
      }
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM