简体   繁体   English

带重新分配的段错误

[英]Segfault with realloc

So I was using malloc in my program and then realloc within a method inside the program. 所以我在程序中使用了malloc,然后在程序内部的方法中重新分配了内存。 After I called this method so many times I would get a "Segmentation fault (core dumped)". 在我多次调用此方法后,我将收到“分段错误(内核已转储)”。

Upon further inspection I realized that for some reason when my pointer goes from 0x25d7d60 or 0x223fae0 (or any address represented by 7 digits (0xHHHHHHH) ) to 0x7f47d370a010 (with more than 7 digits) for example, a segfault is thrown from within the realloc call, realloc wont even return NULL. 经过进一步检查,我意识到,由于某种原因,当我的指针从0x25d7d60或0x223fae0(或任何由7位数字(0xHHHHHHH)表示的地址)变为0x7f47d370a010(超过7位数字)时,会在realloc调用中引发段错误,realloc甚至不会返回NULL。 I fixed this by simply using malloc and then memcpy instead. 我通过简单地使用malloc然后使用memcpy来解决此问题。 However I am very confused at why this happened and wanted to see if any of the users of stackoverflow could shed some light on why this happened. 但是,我对为什么会发生这种情况感到非常困惑,并想看看是否有任何stackoverflow用户可以对为什么会发生这种情况有所了解。

Thanks 谢谢

Here is the relevant code: 以下是相关代码:

 unsigned int* myArray;
 unsigned int num_ints;

 int main()
 {

   num_ints = 100; 
   if((myArray =(unsigned int*) malloc(sizeof(unsigned int)*(num_ints)*3))==NULL)
   {
    std::cout << "Malloc failed!" << std::endl;
    return false;
   }

   .
   .
   .

   //This called when n key is pressed (code left out)
   methodName();
 return true;
 }

 void methodName()
 {

 if((myArray =(unsigned int*) realloc(myArray,sizeof(unsigned int)*(num_ints*4)*3))==NULL)
 {
    std::cout << "Realloc failed!" << std::endl;
    exit(0);
 }

 }

There's a good chance that, by calling "realloc within a method inside the program", you're actually loading it into a local variable which is then thrown away and your program continues to use the older pointer (which has now been freed). 通过调用“程序内部方法中的realloc”,您很有可能实际上是将其加载到局部变量中,然后将其丢弃,程序将继续使用较旧的指针(现已释放)。

We would need to see the code to be certain but, in my experience, that's the one of the major causes of allocation errors. 我们需要确定代码的确定性,但是根据我的经验,这是分配错误的主要原因之一。


Based on what you've shown, there's nothing wrong with what you're doing. 根据您显示的内容,您所做的事情没有错。 It's effectively the same as this code: 它实际上与以下代码相同:

#include <iostream>
#include <cstdlib>
int sz = 1000;
int *buffer = 0;
static int methodName (void) {
    if (sz == 100000)
        sz = 100;
    sz = sz * 10;
    if ((buffer = (int*)realloc (buffer, sz)) == 0) {
        std::cout << "Realloc error" << std::endl;
        return 1;
    }
    return 0;
}
int main(void) {
    int i;
    if ((buffer = (int*)malloc (sz)) == 0) {
        std::cout << "Alloc error" << std::endl;
        return 1;
    }
    for (i = 0; i < 10000000; i++)
        if (methodName() != 0)
            return 1;
    std::cout << "All okay" << std::endl;
    return 0;
}

which works perfectly, doing ten million reallocations. 效果很好,可以进行一千万次重新分配。

So the problems lies outside what you've shown us, perhaps a compiler bug (pretty unlikely if you're using a mainstream compiler) or memory corruption from elsewhere in your code. 因此问题出在您向我们展示的内容之外,可能是编译器错误(如果使用主流编译器,则不太可能出现)或代码其他地方的内存损坏。

If realloc changes the address of the array, then the myarr in the function scope (local) gets the new value, it does not change the myarr variable in the main 如果realloc改变数组的地址,则myarr在功能范围(本地)获得新的值时,它不改变myarr可变main

+---------+
| val1    |  = malloc (whatever);    <--------------------------+
+---------+                                                     |
|myarr    |                                                     |
+---------+                                                     |
|addr_main|                                                     |
+----+----+                                                     |
     |                                                          |
     |                                                          |
     |                                                (NO EFFECT on here)
(value of the myaddr 'val1')                                    |
(in main passed by value)                                       |
(to function)                                                   |
     |                                                          |
     +-------+                                                  |
             |                                                  |
             v                                                  |
methodname (myarr, someint)                                     |
             |                                                  |
             |                                                  |
             V                                                  |
        +---------+                                             |
        |  val1   |    = realloc (myarr, whatever)     ---------+
        +---------+    
        |myarr    |    if 'realloc' returns a new address
        +---------+    it will only overwrite 'val1' with some 'val2' 
        |addr_func|    in this LOCAL copy with address 'addr_func' 
        +---------+
             |
             |
             V
     (destroyed after function return)

您没有在主作用域中更改myArr,而是重新分配可能返回一个新地址,旧地址无效。

The problem is that your methodName function is assigning the new pointer to it's local copy of myArray. 问题在于您的methodName函数正在将新指针分配给它的myArray本地副本。

The quick fix is to make myArray a pointer to a pointer like so: 快速解决方案是使myArray成为如下所示的指针的指针:

void methodName(unsigned int **myArray, unsigned int num_ints)
{
    if((*myArray = (unsigned int *)realloc((*myArray), sizeof(unsigned int)*(num_ints*4)*3)) == NULL)
    {
        std::cout << "Realloc failed!" << std::endl;
        exit(0);
    }
}

and then call it by passing the address of myArr: 然后通过传递myArr的地址来调用它:

methodName(&myArr, n_ints);

That way methodName gets the address of the memory of main() s myArr so that it can write into it. 这样,methodName获取main()的myArr的内存地址,以便它可以写入其中。

As you can see though, having function parameters that output values can get a little hairy so I suggest instead return ing the new address: 如您所见,拥有输出值的函数参数可能会有些麻烦,因此我建议改为return新地址:

unsigned int *methodName(unsigned int *myArray, unsigned int num_ints)
{
    return (unsigned int *)realloc(myArray, sizeof(unsigned int) * (num_ints * 4) *3); 
}

Then it's just a matter of overwriting myArr in main : 然后,只需在main中覆盖myArr

myArr = methodName(myArr, n_ints);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM