【问题标题】:Segmentation error that is still unresolved in C(Linux)在 C(Linux) 中仍未解决的分段错误
【发布时间】:2021-07-18 00:24:35
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <ctype.h>

int main(int argc, char** argv) {
  int shmID;
  char* shmptr, *array, *filearray;
  FILE* infile = fopen(argv[1], "r");
  if (!infile) {
    printf("No file exists\n");
  }
  int length = 0;

  char ch;
  ch = getc(infile);
  while ((ch = getc(infile)) != EOF) {
    filearray[length] = ch;
    length++;

  }
  length++;
  fclose(infile);
  shmID = shmget(IPC_PRIVATE, length, IPC_CREAT | 0666);
  if (shmID < 0) {
    printf("There is an error while creating memory \n");
  }
  int pid = fork();
  if (pid > 0) {
    shmptr = shmat(shmID, NULL, 0);
    if (shmptr == (char * ) - 1) {
      printf("There is an error while attaching memory \n");
    }
    int j = 0;
    while ( * array != '!') {
      if (array[j] >= 'A' && array[j] <= 'Z') {
        array[j] = tolower(array[j]);
      } else if (array[j] >= 'a' && array[j] <= 'z') {
        array[j] = toupper(array[j]);
      } else if (array[j] >= '0' && array[j] <= '9') {
        j--;
      }
      j++;
    }
    * shmptr = '@';

    shmdt(shmptr);
    shmctl(shmID, IPC_RMID, NULL);

  } else if (pid == 0) {
    shmptr = shmat(shmID, NULL, 0);
    if (shmptr == (char * ) - 1) {
      printf("There is an error while attaching memory \n");
    }
    array = shmptr;
    int x;
    for (x = 0; x <= length; x++) {
      * array = filearray[x];
      array++;
    }
    * array = '!';
    while ( * shmptr != '@') {
      sleep(1);
    }

    int k = 0;
    //here we restore the values back into file
    while (*array != '!') {
      printf("%c", array[k]);
      k++;
    }

    shmdt(shmptr);
  } else if (pid < 0) {
    printf("Error\n");
  }
  return 0;
}

这是代码。我打算做的是从文件中获取数据并将其输入到数组中。我们这样做是为了有一个临时数据点来存储。然后我应用适当的检查来查看在创建共享内存或 fork 命令时是否有错误。 在此之后,我们进入我们打算进入的孩子

  1. 附加内存
  2. 检查 1 的错误。
  3. 获取指向 shmptr 的数组(尝试使用另一个 char 数组指针,但仍然遇到问题),该数组最初应为 NULL,但长度为 L(文件中的字符数)
  4. 将文件数组中的值复制到数组中(充当类似于链接列表中的移动头),然后作为最后一个块附加!告诉父母数组结束了。
  5. 使用 @ 作为要添加到数组的字符,这样我们就可以知道等待时间已经结束。

在他的父母中:

  1. 附加内存
  2. 获取数组
  3. 大写、小写并检查值是否为整数(通过 j 删除整数--返回 1 个位置,然后 j++ 移回相同位置)
  4. 在末尾附加一个@。
  5. 当孩子重新运行时,它看到了这个 @ 并且应该打印数组

希望我很清楚。谢谢你的帮助。

【问题讨论】:

  • 缺少发生错误的示例输入文件。
  • 我冒昧地为您修好了牙套和压痕。下次,请确保这是您做的第一件事,而不是最后一件事。没有正确大括号和缩进的代码是无法阅读的,因此您在排除故障时遇到困难也就不足为奇了。

标签: c linux operating-system ipc shared-memory


【解决方案1】:

你的代码有几个问题:

  1. 您检查打开的文件是否有效,但在这种情况下您仍然使用 NULL 指针。

应该是:

FILE  *infile = fopen(argv[1], "r");
if(!infile)
{
    printf("No file exists\n");
    return 1;
}
  1. 指针未初始化,但您已访问它们,这会调用未定义的行为。

您需要在访问这些指针之前对其进行初始化。

char *shmptr;
char *array;
char *filearray;

您可以像这样确定文件大小:

fseek(infile, 0L, SEEK_END);
length = ftell(infile);
fseek(infile, 0L, SEEK_SET);

现在您可以为文件分配内存并一次性读取它,而不是循环:

filearray = malloc(length);
if (!filearray)
{
    // error
    return 1;
}

if(fread(filearray, length, 1, infile) != 1)
{
    // error
    return 1;
}
  1. 如上所述,您访问未初始化的指针,您也可以为array 执行此操作,但在您的示例中尚不清楚它的来源,因此您必须在阅读之前为其分配内存并对其进行初始化。

【讨论】:

  • 感谢您的帮助。还有几个问题 1. 我是否需要 2 个数组来复制我的文件数组以使用子级将其复制到共享内存,然后使用父级执行必要的更改。 2. shmptr 是否像我在链接列表中所说的那样直接被数组复制,您使用辅助指针指向头部,它在这里是否以类似的方式工作? 3. 我一般应该如何更好地使用 Linux C 进行编程?
  • 如果答案有帮助或解决了您的问题,那么您应该投票或标记它。我对shmat 了解不多,所以我无法帮助您。不过,您的 array 指针未初始化。
  • 不幸的是,我无法投票。我刚刚创建了这个帐户以帮助解决这个问题。不知道我在“溢出​​”上睡的是什么帮助网站。另外,如果您可以查看我的“跟进”问题,它可能会很有帮助。无论如何都欣赏这一切。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
相关资源
最近更新 更多