带有realloc的Segfault

时间:2011-10-05 04:47:12

标签: c++ malloc realloc

所以我在我的程序中使用malloc然后在程序内部的方法中重新分配。在我多次调用这个方法后,我会得到一个“Segmentation fault(core dumped)”。

经过进一步检查,我意识到由于某种原因,当我的指针从0x25d7d60或0x223fae0(或任何由7位数字(0xHHHHHHH)表示的地址)变为0x7f47d370a010(超过7位数)时,会从内部抛出一个段错误realloc调用,realloc甚至不返回NULL。我通过简单地使用malloc然后使用memcpy来修复此问题。但是,我很困惑为什么会发生这种情况,并希望看看stackoverflow的任何用户是否能够解释为什么会发生这种情况。

由于

以下是相关代码:

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

 }

4 个答案:

答案 0 :(得分:5)

很有可能通过在程序内部调用“realloc”,你实际上将它加载到一个局部变量中然后被丢弃,你的程序继续使用旧的指针(现在已经被释放)。

我们需要看到代码是确定的,但根据我的经验,这是分配错误的主要原因之一。


根据您所展示的内容,您正在做的事情没有任何问题。它实际上与此代码相同:

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

完美运行,进行了一千万次重新分配。

所以问题不在于你向我们展示的内容,可能是编译器错误(如果你使用的是主流编译器,则非常不可能)或代码中其他地方的内存损坏。

答案 1 :(得分:3)

如果realloc更改了数组的地址,那么函数范围(本地)中的myarr将获得新值,它不会更改myarr变量main 1}}

+---------+
| 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)

答案 2 :(得分:0)

你没有在主范围内更改myArr,realloc可能会返回一个新地址,旧地址无效。

答案 3 :(得分:0)

问题是你的methodName函数正在为它的myArray的本地副本分配新的指针。

快速解决方法是使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);
    }
}

然后通过传递myArr的地址来调用它:

methodName(&myArr, n_ints);

这样,methodName获取main() myArr的内存地址,以便它可以写入。

正如你所看到的,拥有输出值的函数参数可能会有点毛茸茸,所以我建议改为return新地址:

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

然后只需覆盖myArr中的main

myArr = methodName(myArr, n_ints);