So, I need some help. I am working on a project in C++. However, I think I have somehow managed to corrupt my heap. This is based on the fact that I added an std::string
to a class and assigning it a value from another std::string
:
所以,我需要一些帮助。我正在用C ++开发一个项目。但是,我想我已经设法破坏了我的堆。这是基于这样一个事实:我向一个类添加了一个std :: string,并从另一个std :: string中为它赋值:
std::string hello = "Hello, world.\n";
/* exampleString = "Hello, world.\n" would work fine. */
exampleString = hello;
crashes on my system with a stack dump. So basically I need to stop and go through all my code and memory management stuff and find out where I've screwed up. The codebase is still small (about 1000 lines), so this is easily do-able.
使用堆栈转储在我的系统上崩溃。所以基本上我需要停下来查看我的所有代码和内存管理内容,找出我搞砸了的地方。代码库仍然很小(大约1000行),所以这很容易实现。
Still, I'm over my head with this kind of stuff, so I thought I'd throw it out there. I'm on a Linux system and have poked around with valgrind
, and while not knowing completely what I'm doing, it did report that the std::string
's destructor was an invalid free. I have to admit to getting the term 'Heap Corruption' from a Google search; any general purpose articles on this sort of stuff would be appreciated as well.
不过,我对这种东西感到满意,所以我想我会把它扔出去。我正在使用Linux系统并且已经使用valgrind,虽然我不知道我在做什么,但它确实报告了std :: string的析构函数是无效的。我不得不承认从谷歌搜索中获得“堆腐败”一词;关于这类东西的任何通用文章也将受到赞赏。
(In before rm -rf ProjectDir
, do again in C# :D)
(在rm -rf ProjectDir之前,在C#再次执行:D)
EDIT: I haven't made it clear, but what I'm asking for are ways an advice of diagnosing these sort of memory problems. I know the std::string stuff is right, so it's something I've done (or a bug, but there's Not A Problem With Select). I'm sure I could check the code I've written up and you very smart folks would see the problem in no time, but I want to add this kind of code analysis to my 'toolbox', as it were.
编辑:我还没有说清楚,但我要求的是诊断这些记忆问题的建议。我知道std :: string的内容是正确的,所以这是我做过的事情(或者是一个bug,但是选择不是问题)。我确信我可以检查我编写的代码,你很聪明的人会立即看到问题,但我想将这种代码分析添加到我的'工具箱'中,就像它一样。
12 个解决方案
#1
21
These are relatively cheap mechanisms for possibly solving the problem:
这些是可能解决问题的相对便宜的机制:
- Keep an eye on my heap corruption question - I'm updating with the answers as they shake out. The first was balancing
new[]
anddelete[]
, but you're already doing that. - Give valgrind more of a go; it's an excellent tool, and I only wish it was available under Windows. I only slows your program down by about half, which is pretty good compared to the Windows equivalents.
- Think about using the Google Performance Tools as a replacement malloc/new.
- Have you cleaned out all your object files and started over? Perhaps your make file is... "suboptimal"
- You're not
assert()
ing enough in your code. How do I know that without having seen it? Like flossing, no-oneassert()
s enough in their code. Add in a validation function for your objects and call that on method start and method end. - Are you compiling -wall? If not, do so.
- Find yourself a lint tool like PC-Lint. A small app like yours might fit in the PC-lint demo page, meaning no purchase for you!
- Check you're NULLing out pointers after deleteing them. Nobody likes a dangling pointer. Same gig with declared but unallocated pointers.
- Stop using arrays. Use a vector instead.
- Don't use raw pointers. Use a smart pointer. Don't use
auto_ptr
! That thing is... surprising; its semantics are very odd. Instead, choose one of the Boost smart pointers, or something out of the Loki library.
密切关注我的堆腐败问题 - 当他们动摇时,我正在更新答案。第一个是平衡new []和delete [],但你已经在做了。
给valgrind带来更多的乐趣;它是一个很好的工具,我只希望它可以在Windows下使用。我只减慢了你的程序减半,这与Windows等价物相比非常好。
考虑使用Google Performance Tools作为替代malloc / new。
你清理了所有目标文件并重新开始了吗?也许你的make文件是......“次优”
你没有在代码中断言()。我怎么知道没见过它?就像使用牙线一样,没有人在他们的代码中断言()。为对象添加验证函数,并在方法开始和方法结束时调用它。
你在编译墙吗?如果没有,请这样做。
找一个像PC-Lint这样的棉绒工具。像你这样的小应用程序可能适合PC-lint演示页面,这意味着没有为您购买!
删除它们后检查你是否将指针清空。没有人喜欢悬垂的指针。与已声明但未分配的指针相同的演出。
停止使用数组。请改用矢量。
不要使用原始指针。使用智能指针。不要使用auto_ptr!那件事......令人惊讶;它的语义很奇怪。相反,选择一个Boost智能指针,或Loki库之外的东西。
#2
10
We once had a bug which eluded all of the regular techniques, valgrind, purify etc. The crash only ever happened on machines with lots of memory and only on large input data sets.
我们曾经有一个错误,它避开了所有常规技术,valgrind,purify等。崩溃只发生在具有大量内存且仅在大型输入数据集上的机器上。
Eventually we tracked it down using debugger watch points. I'll try to describe the procedure here:
最终我们使用调试器观察点来追踪它。我将尝试在此描述该过程:
1) Find the cause of the failure. It looks from your example code, that the memory for "exampleString" is being corrupted, and so cannot be written to. Let's continue with this assumption.
1)找出失败的原因。从您的示例代码看,“exampleString”的内存正在被破坏,因此无法写入。让我们继续这个假设。
2) Set a breakpoint at the last known location that "exampleString" is used or modified without any problem.
2)在最后一个已知位置设置断点,使用或修改“exampleString”没有任何问题。
3) Add a watch point to the data member of 'exampleString'. With my version of g++, the string is stored in _M_dataplus._M_p
. We want to know when this data member changes. The GDB technique for this is:
3)将监视点添加到'exampleString'的数据成员中。使用我的g ++版本,字符串存储在_M_dataplus._M_p中。我们想知道此数据成员何时更改。 GDB技术是:
(gdb) p &exampleString._M_dataplus._M_p
$3 = (char **) 0xbfccc2d8
(gdb) watch *$3
Hardware watchpoint 1: *$3
I'm obviously using linux with g++ and gdb here, but I believe that memory watch points are available with most debuggers.
我显然在这里使用带有g ++和gdb的linux,但我相信大多数调试器都可以使用内存监视点。
4) Continue until the watch point is triggered:
4)继续,直到触发观察点:
Continuing.
Hardware watchpoint 2: *$3
Old value = 0xb7ec2604 ""
New value = 0x804a014 ""
0xb7e70a1c in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
(gdb) where
The gdb where
command will give a back trace showing what resulted in the modification. This is either a perfectly legal modification, in which case just continue - or if you're lucky it will be the modification due to the memory corruption. In the latter case, you should now be able to review the code that is really causing the problem and hopefully fix it.
gdb where命令将给出一个返回跟踪,显示导致修改的原因。这是一个完全合法的修改,在这种情况下只是继续 - 或者如果你很幸运,它将是由于内存损坏的修改。在后一种情况下,您现在应该能够查看真正导致问题的代码,并希望能够修复它。
The cause of our bug was an array access with a negative index. The index was the result of a cast of a pointer to an 'int' modulos the size of the array. The bug was missed by valgrind et al. as the memory addresses allocated when running under those tools was never "> MAX_INT
" and so never resulted in a negative index.
我们的bug的原因是带有负索引的数组访问。索引是一个指向'int'的指针的结果,模数是数组的大小。 valgrind等人错过了这个漏洞。因为在这些工具下运行时分配的内存地址永远不会是“> MAX_INT”,因此永远不会产生负索引。
#3
7
Oh, if you want to know how to debug the problem, that's simple. First, get a dead chicken. Then, start shaking it.
哦,如果你想知道如何调试问题,这很简单。首先,得到一只死鸡。然后,开始摇晃它。
Seriously, I haven't found a consistent way to track these kinds of bugs down. Because there's so many potential problems, there's not a simple checklist to go through. However, I would recommend the following:
说真的,我还没有找到一种一致的方法来跟踪这些类型的错误。因为存在很多潜在的问题,所以没有一个简单的清单要经过。但是,我建议如下:
- Get comfortable in a debugger.
- Start tromping around in the debugger to see if you can find anything that looks fishy. Check especially to see what's happening during the
exampleString = hello;
line. - Check to make sure it's actually crashing on the
exampleString = hello;
line, and not when exiting some enclosing block (which could cause destructors to fire). - Check any pointer magic you might be doing. Pointer arithmetic, casting, etc.
- Check all of your allocations and deallocations to make sure they are matched (no double-deallocations).
- Make sure you aren't returning any references or pointers to objects on the stack.
熟悉调试器。
在调试器中开始转向,看看你是否能找到任何看起来很可疑的东西。特别检查一下exampleString = hello期间发生了什么;线。
检查以确保它实际上在exampleString = hello上崩溃;线,而不是退出一些封闭的块(可能导致析构函数触发)。
检查你可能正在做的任何指针魔术。指针算术,铸造等
检查所有分配和解除分配以确保它们匹配(没有双重释放)。
确保您没有返回任何引用或指向堆栈上对象的指针。
There are lots of other things to try, too. I'm sure some other people will chime in with ideas as well.
还有很多其他的事情要尝试。我相信其他人也会提出想法。
#4
3
Some places to start:
一些地方开始:
If you're on windows, and using visual C++6 (I hope to god nobody still uses it these days) it's implentation of std::string is not threadsafe, and can lead to this kind of thing.
如果你在Windows上,并使用visual C ++ 6(我希望上帝这些天没有人仍然使用它)它的std :: string的实现不是线程安全的,并且可以导致这种事情。
Here's an article I found which explains a lot of the common causes of memory leaks and corruption.
这是我发现的一篇文章,它解释了许多内存泄漏和损坏的常见原因。
At my previous workplace we used Compuware Boundschecker to help with this. It's commercial and very expensive, so may not be an option.
在我之前的工作场所,我们使用Compuware Boundschecker来帮助解决这个问题。这是商业和非常昂贵的,所以可能不是一个选择。
Here's a couple of free libraries which may be of some use
这里有几个可能有用的免费库
http://www.codeguru.com/cpp/misc/misc/memory/article.php/c3745/
http://www.codeproject.com/KB/cpp/MemLeakDetect.aspx
Hope that helps. Memory corruption is a sucky place to be in!
希望有所帮助。内存损坏是一个很糟糕的地方!
#5
1
It could be heap corruption, but it's just as likely to be stack corruption. Jim's right. We really need a bit more context. Those two lines of source don't tell us much in isolation. There could be any number of things causing this (which is the real joy of C/C++).
它可能是堆损坏,但它可能是堆栈损坏。吉姆是对的。我们真的需要更多的背景。这两行来源并没有孤立地告诉我们。可能有很多事情导致这种情况(这是C / C ++的真正乐趣)。
If you're comfortable posting your code, you could even throw all of it up on a server and post a link. I'm sure you'd gets lots more advice that way (some of it undoubtedly unrelated to your question).
如果您愿意发布您的代码,您甚至可以将其全部放在服务器上并发布链接。我相信你会得到更多的建议(其中一些无疑与你的问题无关)。
#6
1
The code was simply an example of where my program was failing (it was allocated on the stack, Jim). I'm not actually looking for 'what have I done wrong', but rather 'how do I diagnose what I've done wrong'. Teach a man to fish and all that. Though looking at the question, I haven't made that clear enough. Thank goodness for the edit function. :')
代码只是我的程序失败的一个例子(它被分配在堆栈上,Jim)。我实际上并不是在寻找“我做错了什么”,而是“如何诊断我做错了什么”。教一个人钓鱼和所有这些。虽然看了这个问题,但我还没有说清楚。谢天谢地编辑功能。 :')
Also, I actually fixed the std::string problem. How? By replacing it with a vector, compiling, then replacing the string again. It was consistently crashing there, and that fixed even though it...couldn't. There's something nasty there, and I'm not sure what. I did want to check the one time I manually allocate memory on the heap, though:
另外,我实际修复了std :: string问题。怎么样?通过用向量替换它,编译,然后再次替换字符串。它一直在那里崩溃,即使它......也不能解决。那里有些令人讨厌的东西,我不确定是什么。我确实想检查一次我在堆上手动分配内存,但是:
this->map = new Area*[largestY + 1];
for (int i = 0; i < largestY + 1; i++) {
this->map[i] = new Area[largestX + 1];
}
and deleting it:
并删除它:
for (int i = 0; i < largestY + 1; i++) {
delete [] this->map[i];
}
delete [] this->map;
I haven't allocated a 2d array with C++ before. It seems to work.
我以前没有用C ++分配过2d数组。它似乎工作。
#7
1
Also, I actually fixed the std::string problem. How? By replacing it with a vector, compiling, then replacing the string again. It was consistently crashing there, and that fixed even though it...couldn't. There's something nasty there, and I'm not sure what.
另外,我实际修复了std :: string问题。怎么样?通过用向量替换它,编译,然后再次替换字符串。它一直在那里崩溃,即使它......也不能解决。那里有些令人讨厌的东西,我不确定是什么。
That sounds like you really did shake a chicken at it. If you don't know why it's working now, then it's still broken, and pretty much guaranteed to bite you again later (after you've added even more complexity).
听起来你确实在摇晃鸡肉。如果你不知道为什么它现在正在工作,那么它仍然会被破坏,并且几乎可以保证稍后再次咬你(在你增加了更多的复杂性之后)。
#8
1
Run Purify.
It is a near-magical tool that will report when you are clobbering memory you shouldn't be touching, leaking memory by not freeing things, double-freeing, etc.
这是一个近乎神奇的工具,它会报告当你打破记忆时你不应该触摸,通过不释放东西,双重释放等来泄露记忆。
It works at the machine code level, so you don't even have to have the source code.
它适用于机器代码级别,因此您甚至不必拥有源代码。
One of the most enjoyable vendor conference calls I was ever on was when Purify found a memory leak in their code, and we were able to ask, "is it possible you're not freeing memory in your function foo()" and hear the astonishment in their voices.
我曾经遇到的最令人愉快的供应商电话会议之一是当Purify在他们的代码中发现内存泄漏时,我们能够问:“你有没有可能在你的函数foo()中释放内存”并听到他们的声音惊讶。
They thought we were debugging gods but then we let them in on the secret so they could run Purify before we had to use their code. :-)
他们认为我们正在调试上帝,但后来我们让他们了解秘密,这样他们就可以在我们使用他们的代码之前运行Purify。 :-)
http://www-306.ibm.com/software/awdtools/purify/unix/
(It's pretty pricey but they have a free eval download)
(这是相当昂贵的,但他们有免费的eval下载)
#9
1
One of the debugging techniques that I use frequently (except in cases of the most extreme weirdness) is to divide and conquer. If your program currently fails with some specific error, then divide it in half in some way and see if it still has the same error. Obviously the trick is to decide where to divide your program!
我经常使用的调试技术之一(除了最极端的怪异情况)是分而治之。如果您的程序当前失败并出现某些特定错误,请以某种方式将其分成两半,看看它是否仍有相同的错误。显然诀窍是决定在哪里划分你的程序!
Your example as given doesn't show enough context to determine where the error might be. If anybody else were to try your example, it would work fine. So, in your program, try removing as much of the extra stuff you didn't show us and see if it works then. If so, then add the other code back in a bit at a time until it starts failing. Then, the thing you just added is probably the problem.
您给出的示例没有显示足够的上下文来确定错误的位置。如果有其他人试试你的例子,它会工作正常。所以,在你的程序中,尝试删除你没有向我们展示的额外内容,看看它是否有效。如果是这样,那么一次添加其他代码,直到它开始失败。然后,你刚刚添加的东西可能是问题所在。
Note that if your program is multithreaded, then you probably have larger problems. If not, then you should be able to narrow it down in this way. Good luck!
请注意,如果您的程序是多线程的,那么您可能会遇到更大的问题。如果没有,那么你应该能够以这种方式缩小范围。祝好运!
#10
1
Other than tools like Boundschecker or Purify, your best bet at solving problems like this is to just get really good at reading code and become familiar with the code that you're working on.
除了像Boundschecker或Purify这样的工具之外,解决这类问题的最佳方法就是真正擅长阅读代码并熟悉您正在处理的代码。
Memory corruption is one of the most difficult things to troubleshoot and usually these types of problems are solved by spending hours/days in a debugger and noticing something like "hey, pointer X is being used after it was deleted!".
内存损坏是最难解决的问题之一,通常这些类型的问题可以通过在调试器中花费数小时/天来解决,并注意到“嘿,指针X在被删除后被使用!”。
If it helps any, it's something you get better at as you gain experience.
如果它有所帮助,那么随着你获得经验,你会变得更好。
Your memory allocation for the array looks correct, but make sure you check all the places where you access the array too.
您对阵列的内存分配看起来是正确的,但请确保检查您访问阵列的所有位置。
#11
1
Your code as I can see has no errors. As has been said more context is needed.
我能看到你的代码没有错误。如上所述,需要更多背景。
If you haven't already tried, install gdb (the gcc debugger) and compile the program with -g. This will compile in debugging symbols which gdb can use. Once you have gdb installed run it with the program (gdb ). This is a useful cheatsheat for using gdb.
如果您还没有尝试过,请安装gdb(gcc调试器)并使用-g编译程序。这将编译gdb可以使用的调试符号。一旦安装了gdb,就用程序(gdb)运行它。这是使用gdb的有用的cheatsheat。
Set a breakpoint for the function that is producing the bug, and see what the value of exampleString is. Also do the same for whatever parameter you are passing to exampleString. This should at least tell you if the std::strings are valid.
为产生错误的函数设置断点,并查看exampleString的值是什么。对于传递给exampleString的任何参数也要这样做。这至少应该告诉你std :: strings是否有效。
I found the answer from this article to be a good guide about pointers.
我发现本文的答案是关于指针的一个很好的指南。
#12
0
As far as I can tell your code is correct. Assuming exampleString is an std::string that has class scope like you describe, you ought to be able to initialize/assign it that way. Perhaps there is some other issue? Maybe a snippet of actual code would help put it in context.
据我所知,你的代码是正确的。假设exampleString是一个std :: string,它具有你描述的类范围,你应该能够以这种方式初始化/赋值。也许还有其他一些问题?也许一小段实际代码可以帮助将其置于上下文中。
Question: Is exampleString a pointer to a string object created with new?
问题:exampleString是一个指向用new创建的字符串对象的指针吗?
#1
21
These are relatively cheap mechanisms for possibly solving the problem:
这些是可能解决问题的相对便宜的机制:
- Keep an eye on my heap corruption question - I'm updating with the answers as they shake out. The first was balancing
new[]
anddelete[]
, but you're already doing that. - Give valgrind more of a go; it's an excellent tool, and I only wish it was available under Windows. I only slows your program down by about half, which is pretty good compared to the Windows equivalents.
- Think about using the Google Performance Tools as a replacement malloc/new.
- Have you cleaned out all your object files and started over? Perhaps your make file is... "suboptimal"
- You're not
assert()
ing enough in your code. How do I know that without having seen it? Like flossing, no-oneassert()
s enough in their code. Add in a validation function for your objects and call that on method start and method end. - Are you compiling -wall? If not, do so.
- Find yourself a lint tool like PC-Lint. A small app like yours might fit in the PC-lint demo page, meaning no purchase for you!
- Check you're NULLing out pointers after deleteing them. Nobody likes a dangling pointer. Same gig with declared but unallocated pointers.
- Stop using arrays. Use a vector instead.
- Don't use raw pointers. Use a smart pointer. Don't use
auto_ptr
! That thing is... surprising; its semantics are very odd. Instead, choose one of the Boost smart pointers, or something out of the Loki library.
密切关注我的堆腐败问题 - 当他们动摇时,我正在更新答案。第一个是平衡new []和delete [],但你已经在做了。
给valgrind带来更多的乐趣;它是一个很好的工具,我只希望它可以在Windows下使用。我只减慢了你的程序减半,这与Windows等价物相比非常好。
考虑使用Google Performance Tools作为替代malloc / new。
你清理了所有目标文件并重新开始了吗?也许你的make文件是......“次优”
你没有在代码中断言()。我怎么知道没见过它?就像使用牙线一样,没有人在他们的代码中断言()。为对象添加验证函数,并在方法开始和方法结束时调用它。
你在编译墙吗?如果没有,请这样做。
找一个像PC-Lint这样的棉绒工具。像你这样的小应用程序可能适合PC-lint演示页面,这意味着没有为您购买!
删除它们后检查你是否将指针清空。没有人喜欢悬垂的指针。与已声明但未分配的指针相同的演出。
停止使用数组。请改用矢量。
不要使用原始指针。使用智能指针。不要使用auto_ptr!那件事......令人惊讶;它的语义很奇怪。相反,选择一个Boost智能指针,或Loki库之外的东西。
#2
10
We once had a bug which eluded all of the regular techniques, valgrind, purify etc. The crash only ever happened on machines with lots of memory and only on large input data sets.
我们曾经有一个错误,它避开了所有常规技术,valgrind,purify等。崩溃只发生在具有大量内存且仅在大型输入数据集上的机器上。
Eventually we tracked it down using debugger watch points. I'll try to describe the procedure here:
最终我们使用调试器观察点来追踪它。我将尝试在此描述该过程:
1) Find the cause of the failure. It looks from your example code, that the memory for "exampleString" is being corrupted, and so cannot be written to. Let's continue with this assumption.
1)找出失败的原因。从您的示例代码看,“exampleString”的内存正在被破坏,因此无法写入。让我们继续这个假设。
2) Set a breakpoint at the last known location that "exampleString" is used or modified without any problem.
2)在最后一个已知位置设置断点,使用或修改“exampleString”没有任何问题。
3) Add a watch point to the data member of 'exampleString'. With my version of g++, the string is stored in _M_dataplus._M_p
. We want to know when this data member changes. The GDB technique for this is:
3)将监视点添加到'exampleString'的数据成员中。使用我的g ++版本,字符串存储在_M_dataplus._M_p中。我们想知道此数据成员何时更改。 GDB技术是:
(gdb) p &exampleString._M_dataplus._M_p
$3 = (char **) 0xbfccc2d8
(gdb) watch *$3
Hardware watchpoint 1: *$3
I'm obviously using linux with g++ and gdb here, but I believe that memory watch points are available with most debuggers.
我显然在这里使用带有g ++和gdb的linux,但我相信大多数调试器都可以使用内存监视点。
4) Continue until the watch point is triggered:
4)继续,直到触发观察点:
Continuing.
Hardware watchpoint 2: *$3
Old value = 0xb7ec2604 ""
New value = 0x804a014 ""
0xb7e70a1c in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
(gdb) where
The gdb where
command will give a back trace showing what resulted in the modification. This is either a perfectly legal modification, in which case just continue - or if you're lucky it will be the modification due to the memory corruption. In the latter case, you should now be able to review the code that is really causing the problem and hopefully fix it.
gdb where命令将给出一个返回跟踪,显示导致修改的原因。这是一个完全合法的修改,在这种情况下只是继续 - 或者如果你很幸运,它将是由于内存损坏的修改。在后一种情况下,您现在应该能够查看真正导致问题的代码,并希望能够修复它。
The cause of our bug was an array access with a negative index. The index was the result of a cast of a pointer to an 'int' modulos the size of the array. The bug was missed by valgrind et al. as the memory addresses allocated when running under those tools was never "> MAX_INT
" and so never resulted in a negative index.
我们的bug的原因是带有负索引的数组访问。索引是一个指向'int'的指针的结果,模数是数组的大小。 valgrind等人错过了这个漏洞。因为在这些工具下运行时分配的内存地址永远不会是“> MAX_INT”,因此永远不会产生负索引。
#3
7
Oh, if you want to know how to debug the problem, that's simple. First, get a dead chicken. Then, start shaking it.
哦,如果你想知道如何调试问题,这很简单。首先,得到一只死鸡。然后,开始摇晃它。
Seriously, I haven't found a consistent way to track these kinds of bugs down. Because there's so many potential problems, there's not a simple checklist to go through. However, I would recommend the following:
说真的,我还没有找到一种一致的方法来跟踪这些类型的错误。因为存在很多潜在的问题,所以没有一个简单的清单要经过。但是,我建议如下:
- Get comfortable in a debugger.
- Start tromping around in the debugger to see if you can find anything that looks fishy. Check especially to see what's happening during the
exampleString = hello;
line. - Check to make sure it's actually crashing on the
exampleString = hello;
line, and not when exiting some enclosing block (which could cause destructors to fire). - Check any pointer magic you might be doing. Pointer arithmetic, casting, etc.
- Check all of your allocations and deallocations to make sure they are matched (no double-deallocations).
- Make sure you aren't returning any references or pointers to objects on the stack.
熟悉调试器。
在调试器中开始转向,看看你是否能找到任何看起来很可疑的东西。特别检查一下exampleString = hello期间发生了什么;线。
检查以确保它实际上在exampleString = hello上崩溃;线,而不是退出一些封闭的块(可能导致析构函数触发)。
检查你可能正在做的任何指针魔术。指针算术,铸造等
检查所有分配和解除分配以确保它们匹配(没有双重释放)。
确保您没有返回任何引用或指向堆栈上对象的指针。
There are lots of other things to try, too. I'm sure some other people will chime in with ideas as well.
还有很多其他的事情要尝试。我相信其他人也会提出想法。
#4
3
Some places to start:
一些地方开始:
If you're on windows, and using visual C++6 (I hope to god nobody still uses it these days) it's implentation of std::string is not threadsafe, and can lead to this kind of thing.
如果你在Windows上,并使用visual C ++ 6(我希望上帝这些天没有人仍然使用它)它的std :: string的实现不是线程安全的,并且可以导致这种事情。
Here's an article I found which explains a lot of the common causes of memory leaks and corruption.
这是我发现的一篇文章,它解释了许多内存泄漏和损坏的常见原因。
At my previous workplace we used Compuware Boundschecker to help with this. It's commercial and very expensive, so may not be an option.
在我之前的工作场所,我们使用Compuware Boundschecker来帮助解决这个问题。这是商业和非常昂贵的,所以可能不是一个选择。
Here's a couple of free libraries which may be of some use
这里有几个可能有用的免费库
http://www.codeguru.com/cpp/misc/misc/memory/article.php/c3745/
http://www.codeproject.com/KB/cpp/MemLeakDetect.aspx
Hope that helps. Memory corruption is a sucky place to be in!
希望有所帮助。内存损坏是一个很糟糕的地方!
#5
1
It could be heap corruption, but it's just as likely to be stack corruption. Jim's right. We really need a bit more context. Those two lines of source don't tell us much in isolation. There could be any number of things causing this (which is the real joy of C/C++).
它可能是堆损坏,但它可能是堆栈损坏。吉姆是对的。我们真的需要更多的背景。这两行来源并没有孤立地告诉我们。可能有很多事情导致这种情况(这是C / C ++的真正乐趣)。
If you're comfortable posting your code, you could even throw all of it up on a server and post a link. I'm sure you'd gets lots more advice that way (some of it undoubtedly unrelated to your question).
如果您愿意发布您的代码,您甚至可以将其全部放在服务器上并发布链接。我相信你会得到更多的建议(其中一些无疑与你的问题无关)。
#6
1
The code was simply an example of where my program was failing (it was allocated on the stack, Jim). I'm not actually looking for 'what have I done wrong', but rather 'how do I diagnose what I've done wrong'. Teach a man to fish and all that. Though looking at the question, I haven't made that clear enough. Thank goodness for the edit function. :')
代码只是我的程序失败的一个例子(它被分配在堆栈上,Jim)。我实际上并不是在寻找“我做错了什么”,而是“如何诊断我做错了什么”。教一个人钓鱼和所有这些。虽然看了这个问题,但我还没有说清楚。谢天谢地编辑功能。 :')
Also, I actually fixed the std::string problem. How? By replacing it with a vector, compiling, then replacing the string again. It was consistently crashing there, and that fixed even though it...couldn't. There's something nasty there, and I'm not sure what. I did want to check the one time I manually allocate memory on the heap, though:
另外,我实际修复了std :: string问题。怎么样?通过用向量替换它,编译,然后再次替换字符串。它一直在那里崩溃,即使它......也不能解决。那里有些令人讨厌的东西,我不确定是什么。我确实想检查一次我在堆上手动分配内存,但是:
this->map = new Area*[largestY + 1];
for (int i = 0; i < largestY + 1; i++) {
this->map[i] = new Area[largestX + 1];
}
and deleting it:
并删除它:
for (int i = 0; i < largestY + 1; i++) {
delete [] this->map[i];
}
delete [] this->map;
I haven't allocated a 2d array with C++ before. It seems to work.
我以前没有用C ++分配过2d数组。它似乎工作。
#7
1
Also, I actually fixed the std::string problem. How? By replacing it with a vector, compiling, then replacing the string again. It was consistently crashing there, and that fixed even though it...couldn't. There's something nasty there, and I'm not sure what.
另外,我实际修复了std :: string问题。怎么样?通过用向量替换它,编译,然后再次替换字符串。它一直在那里崩溃,即使它......也不能解决。那里有些令人讨厌的东西,我不确定是什么。
That sounds like you really did shake a chicken at it. If you don't know why it's working now, then it's still broken, and pretty much guaranteed to bite you again later (after you've added even more complexity).
听起来你确实在摇晃鸡肉。如果你不知道为什么它现在正在工作,那么它仍然会被破坏,并且几乎可以保证稍后再次咬你(在你增加了更多的复杂性之后)。
#8
1
Run Purify.
It is a near-magical tool that will report when you are clobbering memory you shouldn't be touching, leaking memory by not freeing things, double-freeing, etc.
这是一个近乎神奇的工具,它会报告当你打破记忆时你不应该触摸,通过不释放东西,双重释放等来泄露记忆。
It works at the machine code level, so you don't even have to have the source code.
它适用于机器代码级别,因此您甚至不必拥有源代码。
One of the most enjoyable vendor conference calls I was ever on was when Purify found a memory leak in their code, and we were able to ask, "is it possible you're not freeing memory in your function foo()" and hear the astonishment in their voices.
我曾经遇到的最令人愉快的供应商电话会议之一是当Purify在他们的代码中发现内存泄漏时,我们能够问:“你有没有可能在你的函数foo()中释放内存”并听到他们的声音惊讶。
They thought we were debugging gods but then we let them in on the secret so they could run Purify before we had to use their code. :-)
他们认为我们正在调试上帝,但后来我们让他们了解秘密,这样他们就可以在我们使用他们的代码之前运行Purify。 :-)
http://www-306.ibm.com/software/awdtools/purify/unix/
(It's pretty pricey but they have a free eval download)
(这是相当昂贵的,但他们有免费的eval下载)
#9
1
One of the debugging techniques that I use frequently (except in cases of the most extreme weirdness) is to divide and conquer. If your program currently fails with some specific error, then divide it in half in some way and see if it still has the same error. Obviously the trick is to decide where to divide your program!
我经常使用的调试技术之一(除了最极端的怪异情况)是分而治之。如果您的程序当前失败并出现某些特定错误,请以某种方式将其分成两半,看看它是否仍有相同的错误。显然诀窍是决定在哪里划分你的程序!
Your example as given doesn't show enough context to determine where the error might be. If anybody else were to try your example, it would work fine. So, in your program, try removing as much of the extra stuff you didn't show us and see if it works then. If so, then add the other code back in a bit at a time until it starts failing. Then, the thing you just added is probably the problem.
您给出的示例没有显示足够的上下文来确定错误的位置。如果有其他人试试你的例子,它会工作正常。所以,在你的程序中,尝试删除你没有向我们展示的额外内容,看看它是否有效。如果是这样,那么一次添加其他代码,直到它开始失败。然后,你刚刚添加的东西可能是问题所在。
Note that if your program is multithreaded, then you probably have larger problems. If not, then you should be able to narrow it down in this way. Good luck!
请注意,如果您的程序是多线程的,那么您可能会遇到更大的问题。如果没有,那么你应该能够以这种方式缩小范围。祝好运!
#10
1
Other than tools like Boundschecker or Purify, your best bet at solving problems like this is to just get really good at reading code and become familiar with the code that you're working on.
除了像Boundschecker或Purify这样的工具之外,解决这类问题的最佳方法就是真正擅长阅读代码并熟悉您正在处理的代码。
Memory corruption is one of the most difficult things to troubleshoot and usually these types of problems are solved by spending hours/days in a debugger and noticing something like "hey, pointer X is being used after it was deleted!".
内存损坏是最难解决的问题之一,通常这些类型的问题可以通过在调试器中花费数小时/天来解决,并注意到“嘿,指针X在被删除后被使用!”。
If it helps any, it's something you get better at as you gain experience.
如果它有所帮助,那么随着你获得经验,你会变得更好。
Your memory allocation for the array looks correct, but make sure you check all the places where you access the array too.
您对阵列的内存分配看起来是正确的,但请确保检查您访问阵列的所有位置。
#11
1
Your code as I can see has no errors. As has been said more context is needed.
我能看到你的代码没有错误。如上所述,需要更多背景。
If you haven't already tried, install gdb (the gcc debugger) and compile the program with -g. This will compile in debugging symbols which gdb can use. Once you have gdb installed run it with the program (gdb ). This is a useful cheatsheat for using gdb.
如果您还没有尝试过,请安装gdb(gcc调试器)并使用-g编译程序。这将编译gdb可以使用的调试符号。一旦安装了gdb,就用程序(gdb)运行它。这是使用gdb的有用的cheatsheat。
Set a breakpoint for the function that is producing the bug, and see what the value of exampleString is. Also do the same for whatever parameter you are passing to exampleString. This should at least tell you if the std::strings are valid.
为产生错误的函数设置断点,并查看exampleString的值是什么。对于传递给exampleString的任何参数也要这样做。这至少应该告诉你std :: strings是否有效。
I found the answer from this article to be a good guide about pointers.
我发现本文的答案是关于指针的一个很好的指南。
#12
0
As far as I can tell your code is correct. Assuming exampleString is an std::string that has class scope like you describe, you ought to be able to initialize/assign it that way. Perhaps there is some other issue? Maybe a snippet of actual code would help put it in context.
据我所知,你的代码是正确的。假设exampleString是一个std :: string,它具有你描述的类范围,你应该能够以这种方式初始化/赋值。也许还有其他一些问题?也许一小段实际代码可以帮助将其置于上下文中。
Question: Is exampleString a pointer to a string object created with new?
问题:exampleString是一个指向用new创建的字符串对象的指针吗?