在 Linux 中将数组复制到向量时出现段错误
我正在尝试调试为 Linux 编写的遗留代码。有时,应用程序在以下方法中到达 memcpy 调用时会出现段错误:
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
我不知道为什么会发生这种情况,因为在应用程序运行时此方法被调用数千次,但有时会出现段错误。
任何人都知道如何解决这个问题?
I'm trying to debug a legacy code written for Linux. Sometimes the application gets a segfault when it reaches the memcpy call in the following method:
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;
}
The values are as follows:
_storage.size() is 1000
_wpos is 0
*src points to an array of uint8 with 3 values: { 3, 110, 20 }
cnt is 3
I have no idea why this happens since this method gets called thousands of times during the application's runtime but it sometimes gets a segfault.
Any one has any idea how to solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
从写入的数据来看,您的代码看起来不错。您绝对确定您传递的是正确的 src 指针吗?当您使用 gdb 等调试器运行代码时会发生什么?它应该在出现段错误时停止,然后您可以打印出
_storage.size()
、src
和cnt
的值。我相信您会发现(至少)其中之一根本不是您所期望的。您可能传递了无效的
src
;您可能已经传递了一个大得离谱的cnt
。Your code looks good in terms of the data that is written. Are you absolutely sure that you're passing in the right
src
pointer? What happens when you run the code with a debugger such as gdb? It should halt on the segfault, and then you can print out the values of_storage.size()
,src
, andcnt
.I'm sure you'll find that (at least) one of those is not at all what you're expecting. You might have passed an invalid
src
; you might have passed an absurdly largecnt
.我建议在你的程序上运行 valgrind 。
发现早期内存损坏非常有价值,因为您的程序可能就是这种情况(因为它不是您遇到的系统崩溃)。
I'd suggest to run valgrind on your program.
It's very valuable to spot early memory corruption as it may be the case with your program (since it's not a systematic crash you got).
对于您给出的值,我不明白为什么会出现段错误。您的段错误可能是由于早期的内存管理错误而导致的延迟故障。在某些较早的函数中写入超过向量的末尾可能会导致向量的某些内部成员被损坏,或者您可能意外地释放了向量之前使用的部分内存。我会检查操纵向量的其他函数,看看它们中是否有任何函数正在进行任何可疑的转换。
For the values you give, I can't see why that would segfault. It's possible that your segfault is a delayed failure due to an earlier memory management mistake. Writing past the end of the vector in some earlier function could cause some of the vector's internal members to be corrupted, or you may have accidentally freed part of the memory used by the vector earlier. I'd check the other functions that manipulate the vector to see if any of them are doing any suspicious casting.
我看到向量的大小在增加。我从来没有看到它减少。
除此之外,
vector
内置了详细的内存管理支持。您可以将值插入到末尾:这会将向量扩展至正确的大小,并复制值。
I see the size of the vector increasing. I never see it decreasing.
Next to that,
vector
has expquisit memory management support builtin. You can insert your values right to the end:This will both expand the vector to the right size, and copy the values.
我唯一能想到的是 _storage.resize() 失败(应该抛出 bad_alloc 异常)。
另一种选择是通过调用 push_back() 单独附加每个值(尽管可能慢得多)。
The only thing I can think of is that _storage.resize() fails (which should throw a bad_alloc exception).
Another alternative would be to append each value separately with a call to push_back() (probably far slower though).
我在这里看到一个问题。
memcpy() 函数从内存中复制 n 个字节,因此如果 cnt 是元素数,则在调用 memcpy 时需要 *sizeof(uint8)。
I see one problem here.
The memcpy() function copies n bytes from memory, so if cnt is the number of elements, you need a *sizeof(uint8) in the call to memcpy.
在对我的其他答案的评论中,您说“向量在另一种方法中被清理,因为它是类成员变量。我将测试插入并看看会发生什么”。
线程安全怎么样?您是否绝对确定清除方法不会在调整大小发生时或之后立即清除?由于这是一个“有时”的问题,因此可能是由对
vector
中的内存管理的并发访问引起的。In a comment to my other answer, you said that "The vector gets cleaned up in another method since it is a class member variable. I'll test insert and see what happen".
What about thread-safety? Are you absolutely sure that the clearing method does not clear 'while' the resize is happening, or immediately after it? Since it's a 'sometimes' problem, it may be induced by concurrent access to the memory management in the
vector
.