代码之家  ›  专栏  ›  技术社区  ›  tadm123

(C) 使用具有动态内存分配的阵列

  •  1
  • tadm123  · 技术社区  · 8 年前

    我想创建一个有10个元素的简单整数数组。 我使用动态内存来分配内存中的空间,当我超过这个数量时,它会调用realloc将其大小加倍。 每当我键入“q”时,它就会退出循环并打印数组。

    我知道我的程序充满了错误,所以请引导我找出我的错误所在。

    /* Simple example of dynamic memory allocation */
    
    /* When array reaches 10 elements, it calls
       realloc to double the memory space available */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define SIZE_ARRAY 10
    int main()
    {
        int *a;
        int length=0,i=0,ch;
    
    
        a= calloc(SIZE_ARRAY, sizeof(int));
        if(a == NULL)
        {
            printf("Not enough space. Allocation failed.\n");
            exit(0);
        }
    
        printf("Fill up your array: ");
    
        while(1)
        {
    
            scanf("%d",&ch);
            if(ch == 'q')                  //possible mistake here
                break;
    
            a[length]=ch;
            length++;
    
            if(length % 10 == 0)   //when length is 10, 20, 30 ..
                {
                    printf("Calling realloc to double size.\n");
    
                    a=realloc(a, 2*SIZE_ARRAY*sizeof(int));
                }
    
    
        }
    
        printf("You array is: \n");
        for(;i<length;i++)
            printf("%d ",a[i]);
    
       return 0;
    }
    

    每当我键入“q”时,程序就会崩溃。我是初学者,所以我知道我犯了一个愚蠢的错误。任何帮助都将不胜感激。

    1 回复  |  直到 8 年前
        1
  •  2
  •   deamentiaemundi    8 年前

    你不应该每 realloc() 重新分配() 如果旧的记忆不能足够长,也有使用另一部分记忆的坏习惯。如果失败,您将丢失旧内存中的所有数据。这可以通过使用临时指针指向新内存并在成功分配后交换它们来避免。这需要额外的指针(主要是4或8字节)和交换(最多只需要几个CPU周期 xchg 它在多处理器的情况下使用一个锁,这非常昂贵!)

    #include <stdio.h>
    #include <stdlib.h>
    
    // would normally be some small power of two, like
    // e.g.: 64 or 256
    #define REALLOC_GROW 10
    int main()
    {
      // a needs to be NULL to avoid a first malloc()
      int *a = NULL, *cp;
      // to avoid complications allocated is int instead of size_t
      int allocated = 0, length = 0, i, ch, r;
    
      printf("Fill up your array: ");
      while (1) {
        // Will also do the first allocation when allocated == length
        if (allocated <= length) {
          // realloc() might choose another chunk of memory, so
          // it is safer to work on copy here, such that nothing is lost
          cp = realloc(a, (allocated + REALLOC_GROW) * sizeof(int));
          if (cp == NULL) {
            fprintf(stderr, "Malloc failed\n");
            // but we can still use the old data
            for (i = 0; i < length; i++) {
              printf("%d ", a[i]);
            }
            // that we still have the old data means that we need to
            // free that memory, too
            free(a);
            exit(EXIT_FAILURE);
          }
          a = cp;
          // don't forget to keep the amount of memory we've just allocated
          allocated += REALLOC_GROW;
        }
        // out, if user typed in anything but an integer
        if ((r = scanf("%d", &ch)) != 1) {
          break;
        }
        a[length] = ch;
        length++;
      }
    
      printf("Your array is: \n");
      // keep informations together, set i=0 in the loop
      for (i = 0; i < length; i++) {
        printf("%d ", a[i]);
      }
      fputc('\n', stdout);
      // clean up
      free(a);
    
      exit(EXIT_SUCCESS);
    }
    

    如果您使用的起始值 allocated ,的值 REALLOC_GROW 并在 重新分配() 并更换 if(allocated <= length) 具有 if(1) 您可以触发无内存错误,看看它是否仍打印您之前键入的内容。现在使用以下命令更改副本上的重新分配 a 直接查看是否打印数据。也许情况仍然如此,但不再有保证。