C语言 使用 malloc 的 C 中的错误:大小损坏与 prev_size

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45686572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:42:12  来源:igfitidea点击:

error in C using malloc : corrupted size vs prev_size

cmalloc

提问by ab29007

I found an answer for python but I didn't understand it.

我找到了 python 的答案,但我不明白。

The code is a modified merge sort. It is working fine for a small number of inputs I checked upto 10. But when I run it through an online judge, when number of inputs were high (500) it gave me this error:

代码是修改后的归并排序。对于我检查到 10 的少量输入,它工作正常。但是当我通过在线判断运行它时,当输入数量很高(500)时,它给了我这个错误:

Error in 'a.out': corrupted size vs. prev_size: 0x0000000000d5b8b0
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f3b83a5b7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x80dfb)[0x7f3b83a64dfb]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f3b83a6853c]
a.out[0x4009d1]
a.out[0x400ac7]
a.out[0x400a87]
a.out[0x400aa4]
a.out[0x400a87]
a.out[0x400bc7]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f3b83a04830]
a.out[0x4005b9]
======= Memory map: ========

and it goes for another 15 lines. Why am I getting this error? Is it because of some mistake I am making during dynamic allocation of memory using malloc?

它还有另外 15 行。为什么我收到这个错误?是因为我在动态分配内存时犯了一些错误malloc吗?

Here's my code:

这是我的代码:

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

void *Merge(int *A,int l,int m,int r,int *B,int *F);
void *Merge(int *A,int l,int m,int r,int *B,int *F){
  int i=l,j=m,k=0,*C,x,y=l,z,cSize,temp,*D,*E;

  cSize = r-l;
  C = (int *) malloc (cSize * sizeof(int));
  D = (int *) malloc (cSize * sizeof(int));
  E = (int *) malloc (cSize * sizeof(int));

  while (k < cSize){
    if((j==r) || ((i!=m) && ((A[j]*B[i]) >= (A[i]*B[j])))){
        C[k] = A[i];
        D[k] = B[i];
        E[k] = F[i];
        i++;
        k++;
    }
    if((i>=m) || ((j!=r) && ((A[j]*B[i]) < (A[i]*B[j])))){
        C[k] = A[j];
        D[k] = B[j];
        E[k] = F[j];
        j++;
        k++;
    }
  }
  for(x=0;x<k;x++){
    A[y] = C[x];
    B[y] = D[x];
    F[y] = E[x];
    y++;
  }
  free(C);
  free(D);
  free(E);
}

void *MergeSort(int *A,int left,int right,int *B,int *C);
void *MergeSort(int *A,int left,int right,int *B,int *C){
  int mid,i,j,k=0,l=0,*R,*L;
  if(right - left == 1){
    A[left] = A[left];
  }
  if(right-left > 1){
    mid = (left+right)/2;

    MergeSort(A,left,mid,B,C);
    MergeSort(A,mid,right,B,C);

    Merge(A,left,mid,right,B,C);
  }
}

int main(){
  int n,i=0,newNumt,newNumo,*a,*b,*c;

  scanf("%d",&n);
  a = (int *) malloc (n * sizeof(int));
  b = (int *) malloc (n * sizeof(int));
  c = (int *) malloc (n * sizeof(int));

  for(i=0;i<n;i++){
    scanf("%d %d",&a[i],&b[i]);
    c[i]= i+1;
  }
  MergeSort(a,0,n,b,c);
  for(i=0;i<n;i++){
    printf("%d\n",c[i]);
  }

  return 0;
}

回答by ryyker

This is an old post, but several issues appear left unaddressed, so the following attempts to address some of those you specifically mentioned in your post.

这是一篇旧帖子,但有几个问题似乎没有得到解决,因此以下尝试解决您在帖子中特别提到的一些问题。

As mentioned in the comments the nature of the issues causing your main stated problem was found by setting -Wallduring compile, then running it through a debugger, with up to 20 sets of integer pairs entered upon the prompt.

正如评论中提到的,通过-Wall在编译期间进行设置,然后通过调试器运行它,在提示时输入多达 20 组整数对,可以找到导致您的主要陈述问题的问题的性质。

The following is your complete code with several modifications. Some are only suggestions, but others are responses to compile warnings, some more important than others. These are all commented.

以下是经过多次修改的完整代码。有些只是建议,但有些是对编译警告的回应,有些比其他更重要。这些都是有评论的。

Addressing one of your primary questions: Why am I getting this error? Is it because of some mistake I am making during dynamic allocation of memory using malloc?:
As mentioned my @Jonathan Leffler, it is not likely a problem with memory allocation, but the attempt to access memory that has not been allocated.
The noteworthy run-time error relating to this was seen when running your unmodified code, and is marked with a comment in the Merge()function, where the index kis incremented to a value larger than it should, causing a Dereference of out-of-bounds pointererror. The quick fix was to make the two ifsections mutually exclusive by adding an elseto the second one. This modification does prevent the run-time error, but is not necessarily the right (or only) change needed.

解决您的主要问题之一:为什么我会收到此错误?是不是因为我在使用 malloc 动态分配内存时犯了一些错误?
正如我的@Jonathan Leffler 所提到的,这不太可能是内存分配的问题,而是尝试访问尚未分配的内存。
在运行未修改的代码时会看到与此相关的值得注意的运行时错误,并在Merge()函数中用注释标记,其中索引k增加到大于应有的值,导致对越界指针解除引用错误。快速解决方法是if通过添加一个使这两个部分相互排斥else到第二个。此修改确实防止了运行时错误,但不一定是所需的正确(或唯一)更改。

One other suggestion that I did not address in the code is the selection of variable names. As written many are too cryptic and do not add readability or understanding to what the code is attempting to do. The suggestion would be to use variable names that would allow another person (or even your self, when 3 years from now you are looking at this again.) to immediately understand what the purpose of the variable is.

我在代码中没有提到的另一个建议是选择变量名。正如所写的那样,很多都太神秘了,并没有增加代码试图做什么的可读性或理解性。建议是使用变量名,让另一个人(甚至是你自己,当 3 年后你再次看到这个时。)立即理解变量的目的是什么。

Read the comments for changes to understand why they are there...

阅读更改的评论以了解更改的原因...

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

void *Merge(int *A,int l,int m,int r,int *B,int *F);
void *MergeSort(int *A,int left,int right,int *B,int *C);

int main()
{
   // int n,i=0,newNumt,newNumo,*a,*b,*c;
    int n,i=0,*a,*b,*c; //removed unused newNumt & newNumo

    printf("\nEnter number of integer pairs:\n");//user input instructions
    scanf("%d",&n);
    a = calloc (n, sizeof(int));//see comment in MergeSort for similar
    b = calloc (n, sizeof(int));//suggested change for malloc/calloc
    c = calloc (n, sizeof(int));

    for(i=0;i<n;i++)
    {
        printf("\n%d) Enter two integer values:\n", i);//user input instructions
        scanf("%d %d",&a[i],&b[i]);
        c[i]= i+1;
    }
    MergeSort(a,0,n,b,c);
    for(i=0;i<n;i++)
    {
        printf("%d\n",c[i]);
    }

    return 0; 
}

void *Merge(int *A, int l, int m, int r, int *B, int *F)
{
    //int i=l,j=m,k=0,*C,x,y=l,z,cSize,temp,*D,*E;    
    int i=l,j=m,k=0,*C,x,y=l,cSize,*D,*E;//removed unused z and temp

    cSize = r-l;
   // C = (int *) malloc (cSize * sizeof(int));
   // D = (int *) malloc (cSize * sizeof(int));
   // E = (int *) malloc (cSize * sizeof(int));
    C = calloc (cSize, sizeof(int)); //it is not recommended to cast the return
    D = calloc (cSize, sizeof(int)); //of malloc/calloc/realloc in C
    E = calloc (cSize, sizeof(int)); //changed malloc to calloc to initialize
                                      //variable memory to zero before use

// Only one or the other of the following two if statements should be executed per loop, 
// by running both an access violation occurs causing crash. (eg. when k is incremented twice 
// before being tested.) 
    while (k < cSize)//k is tested only once per loop...
    {
        if((j==r) || ((i!=m) && ((A[j]*B[i]) >= (A[i]*B[j]))))
        {
            C[k] = A[i];
            D[k] = B[i];
            E[k] = F[i];
            i++;
            k++;//if k == csize-1, it will be incremented to k == csize, then go into the next section
        }
        else if((i>=m) || ((j!=r) && ((A[j]*B[i]) < (A[i]*B[j])))) //added else
        {
            C[k] = A[j]; //Dereference of out-of-bounds pointer occurs here when k is too large.
            D[k] = B[j];
            E[k] = F[j];
            j++;
            k++;// ... but possibly increment twice!
        }
    }
    for(x=0;x<k;x++)
    {
        A[y] = C[x];
        B[y] = D[x];
        F[y] = E[x];
        y++;
    }
    free(C);
    free(D);
    free(E);

    return 0; //function prototype requires a return to quiet the warnings
              //Only void function prototypes do not require a return statement

}


void *MergeSort(int *A,int left,int right,int *B,int *C)
{
    //int mid,i,j,k=0,l=0,*R,*L;
    int mid = 0; //removed all unused variables and initialized mid

    if(right - left == 1)
    {
        A[left] = A[left];
    }
    if(right - left > 1)
    {
        mid = (left + right)/2; // integer rounding

        MergeSort(A, left, mid, B, C);
        MergeSort(A, mid, right, B, C);

        Merge(A, left, mid, right, B, C);
    }

    return 0; //function prototype requires a return to quiet the warnings
              //Only void function prototypes do not require a return statement

}