2009-12-16 77 views
0

我正在尝试调试为Linux编写的旧代码。有时,应用程序获取一个segfault,当它达到了以下方法的memcpy调用:将阵列复制到Linux中的矢量时出现segfault

std::vector<uint8> _storage; 
size_t _wpos; 
void append(const uint8 *src, size_t cnt) 
{ 
    if (!cnt) 
    return; 

    if (_storage.size() < _wpos + cnt) 
    _storage.resize(_wpos + cnt); 
    memcpy(&_storage[_wpos], src, cnt); 
    _wpos += cnt; 
} 

的值如下:

_storage.size() is 1000 
_wpos is 0 
*src points to an array of uint8 with 3 values: { 3, 110, 20 } 
cnt is 3 

我不知道为什么会这样,因为这种方法被调用数千在应用程序的运行时期间,但它有时会出现段错误。

任何人有任何想法如何解决这个问题?

+2

你可以。该标准保证&vec [0]是矢量的连续内存存储的开始。矢量的其他成员将存储在&vec [0]到&vec [vec.size() - 1]范围之外。 – 2009-12-16 06:34:10

+0

除了真正的问题之外:以下划线开头的标识符保留给您的编译器/实现。 – xtofl 2009-12-16 08:12:19

+0

线程。可以从不同的线程访问_storage,_wpos和append()吗?如果是这样,则需要同步。 – atzz 2009-12-16 08:19:03

回答

4

您的代码在写入的数据方面看起来不错。你是否确定你传递了正确的src指针?当你使用gdb等调试器运行代码时会发生什么?它应该停止在段错误,然后您可以打印出_storage.size(),srccnt的值。

我相信你会发现(至少)其中一个根本不符合你的期望。你可能通过了一个无效的src;你可能已经通过了一个荒谬的大cnt

+0

我已经使用GDB从核心转储文件中提取这些值。然而,_storage.size()值是我的猜测,因为我无法在那里获得它的值。但其他值是导致段错误的确切值 – 2009-12-16 06:40:13

+0

我看到你在那里做了什么... – caf 2009-12-16 07:44:13

1

对于你给的值,我看不出为什么会出现段错误。由于较早的内存管理错误,您的段错误可能是延迟失败。在一些较早的函数中写入向量的末尾可能会导致某些向量的内部成员被破坏,或者您可能意外地释放了之前由向量使用的部分内存。我会检查操纵矢量的其他函数,看看它们中的任何一个是否在执行任何可疑的投射。

0

我唯一能想到的是_storage.resize()失败(应该抛出bad_alloc异常)。

另一种方法是将每个值分别附加到push_back()的调用(尽管可能要慢得多)。

1

我看到矢量的大小在增加。我从来没有看到它下降。

接下来,vector已经expiryit内存管理支持内置。您可以将您的值直接插入末尾:

vector.insert(src, src+cnt); 

这将同时将矢量扩展到正确的大小,并复制值。

+0

由于它是一个类成员变量,矢量在另一个方法中被清除。我会测试插入,看看会发生什么 – 2009-12-16 07:10:52

0

我在这里看到一个问题。 memcpy()函数从内存中复制n个字节,所以如果cnt是元素的数量,则在调用memcpy时需要* sizeof(uint8)。

+1

sizeof(uint8)很可能是1,所以这可能不是问题。 – 2009-12-16 07:01:51

+0

你有一点,但它真的有所作为,因为类型是uint8? – 2009-12-16 07:11:41

0

在对我的其他答案的评论中,你说过:“由于它是一个类成员变量,因此可以使用另一种方法清理向量,我将测试插入并查看发生了什么”。

线程安全性如何?您是否确定清除方法不会在清除“调整大小”时发生,或者紧随其后?由于这是一个“有时”的问题,因此可能会由并发访问vector中的内存管理引起。

2

我建议在你的程序上运行valgrind。 发现早期内存损坏非常有价值,因为它可能是您的程序的情况(因为它不是系统崩溃)。