【问题标题】:Why does my program crash when transferring strings between char pointers in C?为什么我的程序在 C 中的 char 指针之间传输字符串时会崩溃?
【发布时间】:2016-12-17 08:28:47
【问题描述】:

我现在在 c 中遇到 memcpy() 的问题,希望有人能提供帮助。

我的程序允许用户将字符串输入到 char 指针中,然后计算所有可能的排列。随着排列的生成(用户输入指针变为排列),排列通过 memcpy 复制到第二个 char 指针中。它工作得很好,除非字符串有两个或更多不同的重复字符(例如“CCBB”或“AADD”)。如果用户输入这样的内容,memcpy(甚至 strcpy)会导致程序崩溃。

void Permute(char * word, char ** printPerm, int start, int end)
{   
    if (start == end)
    {
        memcpy(printPerm[permIndex], word, strlen(word) + 1);
        ++permIndex;
    }
    else
    {
        for (int i = start; i <= end; ++i)
        {
            Swap((word + start), (word + i));
            Permute(word, printPerm, start + 1, end);
            Swap((word + start), (word + i));
        }
    }
}

void Swap(char *a, char *b)
{
    char temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

我尝试为两个指针分配更多内存,但结果证明是徒劳的。除了这个,其他一切都有效。

因为我在 Windows (MinGW) 上使用 gcc,所以没有显示我崩溃的详细信息。它只是说“perm.exe 已停止工作”。我使用了一系列 printf() 语句,发现程序在 memcpy() 行崩溃了。

关于代码的一些细节:

“word”字符指针保存用户的输入。它将被程序变形为排列,其内容将被转储到“printPerm”中。 “printPerm” 保存排列的 char 指针数组,稍后将在排列按字母顺序排序并删除任何重复条目时用于打印排列。 "permIndex" 是 "printPerm" 的索引,每次向 "printPerm" 添加排列时都会进行迭代。

抱歉,我没有更多详细信息,但使用文本编辑器和 gcc 意味着我没有得到太多的调试器。似乎只有在字符串包含两个或多个不同的重复字符时,在指针之间传输数据的任何方法都会使程序崩溃。

【问题讨论】:

  • edit您的问题包括minimal reproducible example
  • "用户将字符串输入到 char 指针中" - 坏主意!指针不是数组。您绝对不希望用户在 指针中输入任何内容!
  • 我通过编写自己的 main 函数测试了您的 Permute 函数,它似乎对我测试的输入工作正常。我测试了AABBAABBB 等。我认为您在此处显示的Permute 函数没有问题。你可以编辑你的问题并添加你调用 Permute 的函数吗?如果printPerm[permIndex] 未指向有效内存,并且permIndex 未正确初始化,则会出现问题。
  • 显示 printPerm 的声明。这是可能的故障点。
  • 我怀疑问题在于您的代码计算出printPerm 数组的大小是计算唯一字符。因此“ABCD”有 4 个唯一字符,并且排列数计算正确。但是“AADD”只有 2 个独特的字符。您的 Permute 函数不考虑重复字符,因此它仍会尝试计算 24 个排列。您需要向我们展示您如何确定 printPerm 数组的大小。

标签: c algorithm pointers char memcpy


【解决方案1】:

你很幸运:我的水晶球刚刚修好回来!让我们看看它现在是否有效:

// ALL CHECKS OMMITTED!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int permIndex;

// place the two functions you published here

// Uhmmm...well...but we need one
int factorial(int n)
{
  int f = 1;
  do {
    f *= n;
  } while (--n);

  return f;
}

int main(int argc, char **argv)
{
  int f,i;
  char **pperm;
  char *word;
  size_t length;

  if (argc < 2) {
    fprintf(stderr, "Usage: %s string\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  // work on copy
  length = strlen(argv[1]);
  word = malloc(length + 1);
  strcpy(word, argv[1]);

  // You either allocate memory as you need it but as you compute
  // all combinations first, you need the whole memory for them
  // at once. That means the amount of memory needed is known in
  // advance and can be allocated at once

  f = factorial((int) length);
  // allocate memory for an array of (length)! pointers to char
  pperm = malloc(f * sizeof(char *));
  for (i = 0; i < f; i++) {
    // allocate memory for the n characters plus '\0'
    pperm[i] = malloc(length + 1);
  }

  Permute(word, pperm, 0, length - 1);

  // do something with the list

  // print it
  for (i = 0; i < f; i++) {
    printf("%s\n", pperm[i]);
    // we don't need the memory anymore: free it
    free(pperm[i]);
  }
  // free that array of pointers mjentioned above
  free(pperm);
  // free the memory for the input 
  free(word);

  exit(EXIT_SUCCESS);
}

这是几种方法之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多