使用动态内存分配删除重复项后打印命令行参数会出现分段错误

Printing command line arguments after removing duplicates using dynamic memory allocation gives a segmentation fault

这是我的代码:

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

int isPresent(char *array[], char *string, int dimension) {
  for (int i=0; i<dimension; i++) {
    if (strcmp(array[i], string) != 0) {
      continue;
    } else {
      return 1;
    }
  }
  return 0;
}

int main(int argc, char *argv[]) {
  int dim = 0;
  char **without_duplicates = malloc(dim * sizeof(char *));
  for (int i=1; i<argc; i++) {
    if (!isPresent(without_duplicates, argv[i], dim)) {
      realloc(without_duplicates, (dim + 1) * sizeof(char *));
      without_duplicates[dim] = malloc((strlen(argv[i]) + 1) * sizeof(char));
      strcpy(without_duplicates[dim], argv[i]);
      printf("%s\n", without_duplicates[dim]);
      dim++;
    } else {
      continue;
    }
  }
  printf("%s\n", "Not duplicated arguments:");
  for (int i=0; i<dim; i++) {
    printf("%s\n", without_duplicates[i]);
  }
  return 0;
}

我执行代码:./a.out rome turin rome milan venice milan florence。 但是获取segmentation fault错误。

我尝试调试代码,它一直工作到某个时间点。 例如,它复制 rometurin、丢弃 rome、复制 milan,但不复制 venice 和其他城市。

如果它适用于某些城市,为什么不适用于其他城市? 该程序出现意外行为,并在不同参数的不同点崩溃。

我不知道参数的个数和长度,所以没有重复的新数组必须动态分配。

在您的代码中,您没有将 realloc 的 return 值分配给任何变量

realloc(without_duplicates, (dim + 1) * sizeof(char *));

根据cppreference:

On success, returns the pointer to the beginning of newly allocated memory. The returned pointer must be deallocated with free()or realloc(). The original pointer ptr is invalidated and any access to it is undefined behavior (even if reallocation was in-place).

On failure, returns a null pointer. The original pointer ptr remains valid and may need to be deallocated with free() or realloc().

尝试做类似

的事情
char** temp = realloc(without_duplicates, (dim + 1) * sizeof(char *));

if(temp != NULL) {
    without_duplicates = temp
}
else {
    //handle the unsuccessful allocation
}

注意:同样需要检查malloc()内存分配是否成功。

试试这个:我也允许自己删除代码中的一些无用语句,希望你不要介意

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

int isPresent(char *array[], char *string, int dimension) 
{
  for (int i=0; i<dimension; i++) 
  {
    if (strcmp(array[i], string) == 0)
      return 1;
  }

  return 0;
}

int main(int argc, char *argv[]) 
{
  int dim = 0;
  char ** without_duplicates = malloc(dim * sizeof(char *));

  for (int i=1; i<argc; i++) 
  {
    if (!isPresent(without_duplicates, argv[i], dim)) 
    {
      without_duplicates = realloc(without_duplicates, (dim + 1) * sizeof(char *));
      without_duplicates[dim] = malloc((strlen(argv[i]) + 1) * sizeof(char));

      strcpy(without_duplicates[dim], argv[i]);
      dim++;
    } 
  }

  printf("%s\n", "Not duplicated arguments:");

  for (int i=0; i<dim; i++) 
  {
    printf("%s\n", without_duplicates[i]);
  }

  return 0;
}

您的问题只是没有从 realloc 函数中获取 return 值, C 不是人们可能认为的 high-level 编程语言...如果重新分配一些内存,存储该地址的变量必须知道新分配内存的新地址,因此您必须存储它:

 without_duplicates = realloc(without_duplicates, (dim + 1) * sizeof(char *));

这导致了分段错误,因为在存储新分配的地址之前,您只是跳转到进程上下文中不存在的地址并尝试在其中存储一些数据,结果导致分段错误