【问题标题】:error in C using malloc : corrupted size vs prev_size使用 malloc 的 C 中的错误:损坏的大小与 prev_size
【发布时间】:2018-01-23 00:05:25
【问题描述】:

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

代码是经过修改的归并排序。对于我检查到 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: ========

它还有 15 行。为什么我会收到此错误?是不是因为我在使用malloc动态分配内存时犯了一些错误?

这是我的代码:

#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;
}

【问题讨论】:

  • 你写的越界/释放了两次。使用valgrindvalgrind ./a.out
  • 另外你需要自己找出崩溃的输入并将其添加到问题中
  • A[j], D[k] 超出范围。使用调试器。
  • 当您遇到堆损坏时,问题不在于内存分配本身。问题在于您使用其他内存的方式,特别是您如何修改它。您修改了分配给您使用的范围之外的内存,系统发现其控制数据已损坏,并抱怨——并非无理取闹。例如,如果您要求 16 个字节,并被告知“您可以使用 ptrptr + 15(含)”,但继续在此范围之前或之后修改字节,那么所有的地狱都可以——而且在你的情况下——会崩溃.并且问题通常在远离它的地方被发现。
  • 当我编译你的程序时,我收到了 10 个警告。先解决这个问题。

标签: c malloc


【解决方案1】:

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

如 cmets 中所述,通过在编译期间设置 -Wall,然后通过调试器运行它,在提示符下输入最多 20 组整数对,可以发现导致您的主要问题的问题的性质。

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

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

我在代码中没有解决的另一个建议是变量名的选择。正如所写的那样,许多都太神秘了,并没有增加代码的可读性或理解代码试图做什么。建议使用变量名称,让其他人(甚至是您自己,当您在 3 年后再次查看此内容时)立即了解该变量的用途。

阅读 cmets 以了解更改的原因...

#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

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 2019-05-23
    • 2018-12-15
    • 2021-08-20
    相关资源
    最近更新 更多