首页 > 解决方案 > 手动编码的连接函数错误(分段错误(核心转储))

问题描述

我正在尝试创建一个函数,将 , 和 连接ab一个c名为result.

#include <stdio.h>

const char* concat(char* a, char* b, char* c) {

  char *result;    // Concatenated variable (A + B)
  int i;           // Index of A, B and C
  int ir;          // Index of result

  // result = A
  for(i=0; a[i] != '\0'; i++) {
    ir = i;
    result[ir] = a[i];
  } // → for

  // result = A + B
  ir++;
  for(i = 0; b[i] != '\0'; i++) {
    if (i == 0)
      ir = ir + i;
    result[ir] = b[i];
  } // → for

  // result = A + B + C
  ir++;
  for(i = 0; c[i] != '\0'; i++) {
    ir = ir + i;
    result[ir] = c[i];
  } // → for

  return result;
} // → concatenate()

但是当我使用以下块编译和运行时,它会导致Segmentation fault (core dumped)错误。我已经搜索过它(什么是分段错误?)但没有得到洞察力。我究竟做错了什么?

int main() {

  char* a = "1234567";
  char* b = "abcdefg";
  char* c = "_______";


  printf("%s", concat(a, b, c));

}

错误:

Segmentation fault (core dumped)

标签: c

解决方案


显示的代码试图将数据存储到未定义的缓冲区 ( result) 中,这并非不合规矩。有些人必须通过传入有界输出缓冲区来分配空间,无论是您的函数还是调用者。

使用分配内存机制,您必须提前获取所有字符串的完整大小,以便您可以一次分配完整的块。分配完整块后,一次复制一个字符串。

char *concat3(const char *a, const char *b, const char *c)
{
    // get the required size in advance
    size_t n = 0;

    for (const char *ap = a; *ap; ap++) n++;
    for (const char *bp = b; *bp; bp++) n++;
    for (const char *cp = c; *cp; cp++) n++;

    char *result = malloc(n + 1);

    char *op = result;

    while (*op = *a++) op++;
    while (*op = *b++) op++;
    while (*op = *c++) op++;

    return result;
}

另请注意,参数const char *不是char *为了确保每个人都知道concat3——我更改了名称——不会写入这些输入缓冲区。

但是,返回值不能是const因为你必须释放它,我希望你记得这样做。

编辑我添加了一个不同的版本,它写入有界输出缓冲区,因此函数中不需要内存分配,因为调用者负责它:

char *concat(char *obuf, size_t osize, const char *a, const char *b, const char *c)
{
    char *obuf_save = obuf;

    const char *obuf_max = obuf + osize - 1;

    while (obuf < obuf_max  &&  (*obuf = *a++)) obuf++;
    while (obuf < obuf_max  &&  (*obuf = *b++)) obuf++;
    while (obuf < obuf_max  &&  (*obuf = *c++)) obuf++;

    *obuf = 0;

    return obuf_save;
}

关键部分是传递输出缓冲区和大小,它保证不会覆盖缓冲区的末尾。

关键缺点:您无法判断它是否被截断。如果这很重要,取决于您的应用程序。


推荐阅读