【问题标题】:concating char* in c fails do to segmentation fault由于分段错误,c 中的连接 char* 失败
【发布时间】:2014-12-08 12:57:47
【问题描述】:

我试图创建两个路径,以便将文件从一个文件夹复制到另一个文件夹。 我第二次尝试连接 args [1] 时遇到分段错误。 尝试使用 strcpy 将单元格复制到另一个字符,但它没有帮助。还有很多我没有成功的东西。 我猜这些字符串命令的某些东西弄乱了我的 char 数组,并且不允许我执行 concat twise。 路径应该是形式 “服务器/文件#” 或“客户端#/文件#” # 是来自 args 的参数。 我环顾四周,看到了一些类似的东西,但不完全是。 请帮忙。

所有需要的“包含”都在里面。

void copy_file(char *args[]){
char dst_path[100],src_path[100];

memset(dst_path,0,100);
memset(src_path,0,100);

strcpy(dst_path,"Client");
strcat(dst_path,args[0]);
strcat(dst_path,"/File");
strcat(dst_path,args[1]);

strcpy(src_path,"Server/File");
strcat(src_path,args[1]);
}

【问题讨论】:

  • 另外,i 从未被声明过,你应该真正使用 memset。
  • 两者都做了...仍然没有解决方案..
  • 旁注:您以strcpy 开头的事实使得对memset 的调用变得多余。顺便说一句,你也可以在声明时设置它们(在性能方面它或多或少与调用 strcpy 相同,但在代码方面它会更干净)。
  • 只是像这样打印它们- printf("%s , %s",args[0],args[1]);工作正常。

标签: c string segmentation-fault


【解决方案1】:

这段代码应该是段错误的,因为没有边界检查,你可以很容易地溢出目标缓冲区。

此外,您不检查 args[] 数组中的元素数。参数可能比您预期的要少,可能args[1] 是NULL。


修复:

  1. 检查args[]数组中的元素个数。

  2. 计算最终字符串所需的缓冲区大小,分配该大小的缓冲区,然后格式化字符串。或者,使用snprintf 在一次调用中格式化字符串。 snprintf 会为您进行绑定检查,以免您的目标缓冲区溢出,例如:

    char dst_path[16384];
    int n = snprintf(dst_path, sizeof dst_path, "Client %s /File %s", args[0], args[1]);
    if(n >= sizeof dst_path)
        // dst_path is not large enough
    

【讨论】:

  • 嘿,在 qeustion 的预览版中,缓冲区的大小是应该的,但这里的人告诉我它会流出。所以我把它放大了。我现在正在检查 snprintf。
【解决方案2】:

希望你能从中收集到你走错的地方。经 GCC 4.8.3 测试。总而言之,你的缓冲区溢出了。

/* gcc -g -Wall -Wextra main.c */
#include <assert.h>
#include <string.h>

#define BUFSIZE 30

void copy_file(char* args[]) {
  char dst_path[BUFSIZE];
  char src_path[BUFSIZE];
  int i;

  for (i = 0; i < 30; i++) { //initializing - tried without it too.
    dst_path[i] = 0;
    src_path[i] = 0; }

  assert(strlen(dst_path) + strlen("Client") < BUFSIZE);
  strcpy(dst_path, "Client");
  assert(strlen(dst_path) + strlen(args[0]) < BUFSIZE);
  strcat(dst_path, args[0]);
  assert(strlen(dst_path) + strlen("/File") < BUFSIZE);
  strcat(dst_path, "/File");
  assert(strlen(dst_path) + strlen(args[1]) < BUFSIZE);
  strcat(dst_path, args[1]);

  assert(strlen(src_path) + strlen("Server/File") < BUFSIZE);
  strcpy(src_path, "Server/File");
  assert(strlen(src_path) + strlen(args[1]) < BUFSIZE);
  strcat(src_path, args[1]); }

int main(int argc, char* argv[]) {
  copy_file(&argv[1]);
  return 0; }

【讨论】:

  • 您不需要用零初始化整个缓冲区。只有第一个元素。
  • @MaximYegorushkin,真的。我正在尽量减少对相关代码的更改。
  • @MaximYegorushkin,很公平。如果我真的要尽量减少代码更改,我也应该将死变量留在那里。
【解决方案3】:

您遇到缓冲区溢出的主要原因之一很可能是您使用了strcpy。这没有固定的复制长度,因此如果您的字符串没有以 NULL 字符 \0 终止,则不属于字符串的内存也将被复制。你应该使用的是strncpy;然后您可以使用strlen 在添加终止NULL 字符后获取字符串的长度。写入缓冲区后始终将缓冲区的最后一个字符设置为 NULL 是一种很好的做法。

【讨论】:

    猜你喜欢
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 2015-12-16
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 2019-05-27
    相关资源
    最近更新 更多