- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个实现引用计数系统的库。在 Debug模式下,我在分配和删除值时打印出来。编译测试程序并运行后,它并没有真正运行而是实际删除了自己并留下了一个stackdump文件。有趣的是,这只发生在我使用一个像基于范围的引用管理器一样实现的小助手模板类时(当对象助手对象被销毁时减少引用计数)。
甚至 GDB 也帮不了我,因为当我指示它运行 main.exe
时,它说它无法打开进程。
因此,首先,我查看了导致所描述行为的主程序。
// snippet 1
void test1() {
Handle<String> v = String::New("Fooo!");
std::cout << v->Get() << "\n";
}
将其更改为以下内容使程序再次运行:
// snippet 2
void test1() {
String* v = String::New("Fooo!");
std::cout << v->Get() << "\n";
v->Decref();
}
但我知道 Handle<T>
类实际上工作得很好,因为以下函数再次运行良好,没有问题或未释放值。 (@agbinfo)String
类是 Value
的子类. Handle
模板旨在与 Value
配合使用类,因此不需要手动调用 Value::Decref()
当不再需要该值时。
// snippet 3
Value* test2() {
Handle<HashMap> map = HashMap::New();
Handle<Value> a = String::New("The Answer");
Handle<Value> b = Int::New(42);
map->Put(a, b);
// It's easier to use the static getter functions when
// using the Handle helper class because it makes headache
// to cast them.
a = map->AsString();
std::cout << String::Get(a) << "\n";
// Overwrite the existing entry in the map.
a = String::New("The Answer");
b = vv::null();
map->Put(a, b);
// But we could also get an actual pointer to the String. We
// just have to make sure to decrease the reference count as
// we don't have the Handle helper class that does that based
// on the scope.
String* str = map->AsString();
std::cout << str->Get() << "\n";
str->Decref();
// The ownership of the returned Value* is transfered to the
// caller with Handle<T>::Release()
return a.Release();
}
有趣的是,当我替换 return a.Release();
时在test2()
与 return nullptr;
并调用 test1()
但从来没有 test2()
,程序再次正常运行。
我恢复到程序崩溃的状态,并试图在代码更深的地方找到问题。我查看了 vv::Value
时完成的日志记录对象被创建或删除。删除 utils::typestr(Type())
部分来自 vv::Value::Free()
让程序再次运行!
class Value {
protected:
/**
* Must be invoked when an object was allocated and
* constructed.
*/
virtual void Init()
{
#ifdef VV_DEBUG
if (vv::GetFlag(SystemFlags_LogGeneration))
logging::LogValue(this, "Created " + utils::typestr(Type()));
#endif
}
/**
* Is invoked when the object is about to be deallocated
* from vv::Value::Decref().
*/
virtual void Free()
{
#ifdef VV_DEBUG
if (vv::GetFlag(SystemFlags_LogGeneration))
logging::LogValue(this, "Deleted " /* + utils::typestr(Type()) */);
#endif
}
public:
// ...
};
现在,在 vv::utils::typestr()
,我通过将其字节解释为字符将整数转换为字符串,因为可以从 vv::Value::Type()
返回的值声明为
enum {
Type_Null = 'null',
Type_Bool = 'bool',
Type_Int = 'intg',
Type_Double = 'dble',
Type_String = 'strn',
Type_Array = 'arry',
Type_List = 'list',
Type_HashMap = 'hmap',
};
所以 typestr()
的代码是
inline std::string typestr(int id)
{
const char* buffer = reinterpret_cast<const char*>(&id);
std::string result = "";
for (size_t i=0; i < sizeof(int); i++) {
result.push_back(buffer[i]);
}
// Reverse the string if we are on a little-endian system.
if (vv::utils::bigendian()) {
std::reverse(result.begin(), result.end());
}
return result;
}
对于 stackdump,不幸的是它并不是每次都生成,我目前无法重现它来获取最近的 stackdump。但是其中一个生成的文件看起来很像这样:
Exception: STATUS_ACCESS_VIOLATION at eip=004022A8
eax=0028ABE4 ebx=0028AC6C ecx=00000001 edx=0000001C esi=00000000 edi=610071D0
ebp=0028AC48 esp=0028AC20 program=C:\Users\niklas\Desktop\cpp-vv\main.exe, pid 6412, thread main
cs=0023 ds=002B es=002B fs=0053 gs=002B ss=002B
Stack trace:
Frame Function Args
0028AC48 004022A8 (00000001, 0028AC6C, 80010100, 61007FDA)
0028ACF8 61008039 (00000000, 0028CD84, 610071D0, 00000000)
0028CD58 61005E84 (0028CD84, 00000000, 00000000, 00000000)
0028FF28 61005FF6 (610071D0, 00000000, 00000000, 00000000)
0028FF48 61006F54 (00402225, 00000000, 00000000, 00000000)
0028FF68 00402592 (00402225, 00000000, 00000000, 00000000)
0028FF88 00401015 (FFFDE000, 0028FFD4, 77C49F72, FFFDE000)
0028FF94 773F336A (FFFDE000, 76B6F19F, 00000000, 00000000)
0028FFD4 77C49F72 (00401000, FFFDE000, 00000000, 00000000)
0028FFEC 77C49F45 (00401000, FFFDE000, 00000000, 78746341)
End of stack trace
g++ -std=c++11 -g -Wno-multichar -Iinclude/ -DVV_DEBUG src/main.cpp -c -oobj/src/main.o
g++ -std=c++11 -g -Wno-multichar -Iinclude/ -DVV_DEBUG src/vv/system.cpp -c -oobj/src/vv/system.o
g++ -std=c++11 -g -Wno-multichar -Iinclude/ -DVV_DEBUG src/vv/logging.cpp -c -oobj/src/vv/logging.o
g++ -std=c++11 -g -Wno-multichar -Iinclude/ -DVV_DEBUG src/vv/Types.cpp -c -oobj/src/vv/Types.o
g++ -std=c++11 -g -Wno-multichar -Iinclude/ -DVV_DEBUG src/vv/Value.cpp -c -oobj/src/vv/Value.o
g++ -Wno-multichar -Iinclude/ -DVV_DEBUG obj/src/main.o obj/src/vv/system.o obj/src/vv/logging.o obj/src/vv/Types.o obj/src/vv/Value.o -o main.exe
Windows 7 64 位上的 Cygwin
g++ (GCC) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
到目前为止,这似乎让程序运行起来了。但是你知道这个问题可能来自哪里吗?就我而言,我无法在 typestr()
中发现问题.也许您作为经验丰富的开发人员可以识别并告诉我一些模式?
最佳答案
您的防病毒软件的检测试探法可能仅在非常特殊、看似随意的情况下才会将您的程序错误地识别为病毒。尝试暂时禁用实时系统保护。
关于c++ - 程序自行删除,不启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22949467/
我发现以下帖子非常有帮助: How to pickle yourself? 但是,此解决方案的局限性在于,重新加载类时,它不会以其“运行时”状态返回。即它将重新加载所有变量等以及类在转储时的一般状态.
我是一名优秀的程序员,十分优秀!