realloc:没有足够的空间

Posted

技术标签:

【中文标题】realloc:没有足够的空间【英文标题】:realloc: Not enough space 【发布时间】:2012-10-08 08:12:42 【问题描述】:

Windows 7、64 位、MinGW 工具集,以下代码:

m_data = reinterpret_cast<SampleType *>(realloc(m_data, m_size + v));  
if (NULL == m_data)  
    perror ("realloc failed");  
    exit(-1);  

失败并显示消息realloc failed: Not enough space 即使我再询问 100 个字节,它也会发生。而且无论我是使用 malloc(带有相应的指针重新分配)还是 realloc。我总是一样。 计算机报告超过 1GB 的可用内存。

以上是方法的片段。下面是它的完整代码。 关键是当this 方法的m_data 等于NULL 时,此方法第一次分配内存,并在后续调用中扩大它。所以,请看下面

Wave & operator+= (const Wave wave)
    if (NULL != m_data)
        m_data = reinterpret_cast<SampleType *>(realloc(m_data, m_size + wave.DataSize()));
        if (NULL == m_data)
        perror ("realloc failed");
        exit(-1);
        
     else 
        m_data = reinterpret_cast<SampleType *>(malloc(wave.DataSize()));
        m_size = 0; // just for sure
    
    /* this code fragment I used instead of realloc's one to prove that realloc is not a root of error cause
    SampleType *t_buf = reinterpret_cast<SampleType *>(malloc(m_size + wave.DataSize()));
    if (!t_buf) perror ("malloc failed"); exit(-1);
    memcpy (t_buf, m_data, m_size);
    free (m_data);
    m_data = t_buf;
    */
    memcpy (m_data + m_size, wave.SampleBuffer(), wave.DataSize());
    m_size += wave.DataSize();
    return *this;
;

因此,第一次使用 malloc 分配内存。不要怀疑。

调试器会话跟踪。

Breakpoint 2, _fu17___ZSt4cout () at ../sound_windows/Sound.h:192  
192             if (NULL != m_data)  
(gdb) print *this  
$2 = static CHANNEL_NUMBER = <optimized out>, m_format = wFormatTag = 1, nChannels = 2,nSamplesPerSec = 44100, nAvgBytesPerSec = 176400, nBlockAlign = 4,  
    wBitsPerSample = 16, cbSize = 18, m_duration = 0, m_data = 0x0, m_size = 0  
(gdb) cont  
Continuing.  

Breakpoint 2, _fu17___ZSt4cout () at ../sound_windows/Sound.h:192  
192             if (NULL != m_data)  
(gdb) print *this  
$3 = static CHANNEL_NUMBER = <optimized out>, m_format = wFormatTag = 1, nChannels = 2,nSamplesPerSec = 44100, nAvgBytesPerSec = 176400, nBlockAlign = 4,  
    wBitsPerSample = 16, cbSize = 18, m_duration = 0.00451559993, m_data = 0x75d9e0, m_size = 800  
(gdb) cont  
Continuing.  
tried to allocate 800+100 bytes  
realloc failed: Not enough space  
[Inferior 1 (process 6132) exited with code 037777777777]  

【问题讨论】:

你在调试器下看到的m_size + v 的值是多少? 您确定 m_data 已经分配了吗?另外,究竟是什么给出了“空间不足”的错误?我只看到您通过perror 报告的“realloc failed”,realloc 可能由于其他原因返回 NULL。 如果删除 reinterpret_cast 也会发生同样的情况? @KillianDS:是的,我确定 m_data 已经分配了。该消息发生在 realloc retuns NULL 之后。以上就是我所掌握的所有信息。 m_data 是使用malloc 还是其他方式分配的? realloc 仅重新分配使用 malloc 分配的内存。 【参考方案1】:

错误的根源是由于内存管理函数中的内存寻址混乱而导致堆栈破坏。例如,在下面的代码行中

memcpy (m_data + m_size, wave.SampleBuffer(), wave.DataSize()); 

m_data + m_size 不是它的本意,因为m_data 指向一个两字节大小的类型,而m_size 是字节大小。所以m_data + m_size 不会将指针偏移到m_data 的末尾,而是偏移到两倍远的距离。

【讨论】:

【参考方案2】:

我怀疑现有的m_data 没有直接分配给mallocrealloc 仅重新分配最初使用 malloc 分配的块。

这是因为它使用了堆内部数据结构的知识。如果块不是来自堆,如果你幸运的话你会收到一条消息,如果你不幸运你的程序就会崩溃。

“空间不足”消息只是分配失败的一般返回。

编辑: 在扩展版本中,您是否在构造函数中将m_data 初始化为NULL?这不会自动发生,如果你不这样做,它通常会包含一个垃圾值。

换句话说,if (NULL != m_data) 分支永远不会被命中,因为除非你初始化它,否则 m_data 不会以 NULL 开始。

【讨论】:

好的,伙计们,在最初的问题中查看整个代码和相应的 cmets。 @OlegG,看什么?如果您正在编辑,请务必显示 m_data 的分配位置。 @OlegG,我在答案中添加了更多内容。 是的,我在构造函数中将 m_data 初始化为 NULL。已经检查过了。 @olegG,在该行设置断点并在调试器中检查。

以上是关于realloc:没有足够的空间的主要内容,如果未能解决你的问题,请参考以下文章

如果没有顺序的内存空间,realloc 会做啥?

在不移动数据的情况下在 CUDA 中实现 realloc

malloc,calloc,realloc解析

realloc函数详解

使用 realloc() 使 memmove() 安全 [重复]

realloc ------ 扩大malloc得到的内存空间