在c中使用指针覆盖内存的可能性?

possibility of memory overwrite using pointers in c?

我已经根据 K&R c book

编写了自己的 getline 函数
void getline(char * const str) 
{
  int c;
  char* temp = str;
  while ((c=getchar()) != '\n') {
    *temp = c;
    temp++;
  }
  *temp = '[=10=]'
}

用于初始化字符串

char *str1, *str2;
printf("Type string 1: ");  
getline(str1);
printf("Type string 2: ");  
getline(str2);

只是奇怪,如果str1str1指向的内存位置非常接近,那么getline(str2)会覆盖字符串1中的内容吗?

有可能,我该如何避免呢?谢谢!

更新:

是的,程序停止执行上面的代码片段,但下面的代码有效:

#include <stdio.h>
main()
{
  char* str;
  char* temp = str; 
  int c;
  while ((c=getchar()) != '\n') {
    *temp = c;
    ++temp;
  }
  *temp = '[=12=]';
  printf("%s\n", str);
}

这里的str也是未初始化的字符指针,但是为什么不报错呢?

你拥有的是 Undefined Behavior.

解释:

您声明了两个指向 char 的指针:

char *str1, *str2;

但你还没有初始化它们。它们指向一些“随机”内存位置,因为它们未初始化。

然后,您将 str1str2 传递给 getline,这里:

char* temp = str;

temp 指向 str 指向的位置。然后,在循环中,

*temp = c;

您写入此内存位置。这将写入无效的内存位置。并调用 UB.

修复:

  1. 您可以使用固定大小的自动数组:

    char str1[101], str2[101];
    

    请注意,您应该在 getline 函数的循环中添加一个检查,当用户输入 100 个字符时,该循环会中断循环,这样就不会出现 buffer overflow

  2. 更好的解决方案是使用动态内存分配。为此,您需要使用 mallocrealloc。这些函数需要 stdlib.h header.

    固定代码 (未测试):

    char* getline() 
    {
      char* str;
      int c, size = 10, counter = 0;
    
      str = malloc(size); /* Allocate `size` memory */
    
      if(str == NULL)
      {
        printf("malloc failed to allocate memory");
        exit(-1); /* Exit the program */
        /* Or
        return NULL;
        */
      }
    
      while ((c = getchar()) != '\n' && c != EOF) { /* Added check for EOF as well */
        str[counter] = c;
        counter++;
    
        if(counter == size)
        {
          char* temp = str; /* Backup in case realloc fails */
          size += 10; /* Which is the same as `size = size + 10` */
          str = realloc(str, size); /* realloc size(20) memory */
    
          if(str == NULL) /* If realloc failed */
          {
            printf("reallocing memory failed");
            str = temp; /* str is NULL, retrieve the original contents */
            break; /* Break out of the loop */
          }
        }
      }
    
      str = realloc(str, counter + 1); /* realloc `counter + 1` memory */
    
      str[counter] = '[=14=]';
      return str;
    }
    

    并且在调用函数中,

    char* str1 = getline();
    if(str1)
      puts(str1);
    free(str1);
    
    
    char* str2 = getline();
    if(str2)
      puts(str2);
    free(str2);
    

str1str2 未初始化,因此它将是未定义的行为。您可以访问不允许的内存,这会使您的程序崩溃。

您必须为每个指针分配足够的内存并将其大小传递给获取行函数以确保您只在分配的内存中写入。

str1str2 是 uninitialized.Right 现在您在无效(或未授权)内存位置写入 (*temp = c;) 调用 UB.

首先你需要为 str1str2 分配内存。

str1=malloc(100);     // check return 
str2=malloc(100);

能够写入该内存位置。

Just wonder that, what if the memory locations str1 and str1 point to are very close, then getline(str2) overwrites contents in string 1?It that's possible how could I avoid it?

并且就您而言,由这些 malloc 分配的内存不会重叠(将是两个不同的传染性内存块),因此如果您也倾向于在这些内存位置之外写入,您将调用未定义的行为如果你幸运的话分段错误)。所以,恕我直言,不会有任何 str2 覆盖 str1.

的情况