我正在编写一个使用实时音频分析的iOS应用。它有一个间歇性的崩溃(大约5分钟后,仅在模拟器上。虽然这意味着它不是一个运输应用程序的关注,它肯定是一个发展的痛苦,而且,如果我跟踪它,我会在晚上睡得更好崩溃总是发生在同一个地方,在我的音频分析代码的静态函数中:崩溃发生在这里:
struct Tone {
// (other stuff)
// THIS is the problem function:
static bool dbCompare(Tone const& l, Tone const& r) { return l.db < r.db; }
}
};
还在这里:
Tone const* findTone(double minfreq = 70.0, double maxfreq = 700.0) const {
if (m_tones.empty()) { m_oldfreq = 0.0; return NULL; }
double db = std::max_element(m_tones.begin(), m_tones.end(), Tone::dbCompare)->db;
Tone const* best = NULL;
double bestscore = 0;
for (tones_t::const_iterator it = m_tones.begin(); it != m_tones.end(); ++it) {
// ON THIS LINE. Is my iterator somehow becoming invalid?:
if (it->db < db - 20.0 || it->freq < minfreq || it->age < Tone::MINAGE) continue;
if (it->freq > maxfreq) break;
double score = it->db - std::max(180.0, std::abs(it->freq - 300.0)) / 10.0;
if (m_oldfreq != 0.0 && std::fabs(it->freq/m_oldfreq - 1.0) < 0.05) score += 10.0;
if (best && bestscore > score) break;
best = &*it;
bestscore = score;
}
m_oldfreq = (best ? best->freq : 0.0);
return best;
}
(好吧,这个修复,下面,对@Justin来说是错误的。我现在离开它是为了完整,至少现在)。 为了在任何可能传入的空指针中生存,我添加了一些检查并尝试进行错误处理:
struct Tone {
static bool dbCompare(Tone const& l, Tone const& r) {
try {
if (&l == NULL || &r == NULL) throw 1;
return l.db < r.db;
throw 1;
}
catch(int e) {
NSLog(@"AUDIO ERROR: Pointer invalid. %d", e);
}
return 0;
}
};
没有骰子,它仍然在同一条线上失败。我误解了试试投掷吗?错误是否正在进一步回到管道?
这段代码来自开源摇滚乐队风格的游戏Performous,他们的游戏没有这个问题。 (它也不适用于iPhone。)所以这让我希望能消除模拟器崩溃......
编辑2 Per @Justin我正在使用GuardMalloc运行。模拟器5.0立即崩溃 - 似乎有some SO questions about this但是现在我正在运行4.3模拟器,它以正常方式发生崩溃,但除此之外别无其他我知道如何使用:
#0 0x94f38c97 in malloc_error_break ()
#1 0x94efa4ce in szone_error ()
#2 0x94efc35f in allocate_pages ()
#3 0x94f013cc in allocate_pages_securely ()
#4 0x94f019b8 in szone_malloc_should_clear ()
#5 0x94f0266b in szone_malloc ()
#6 0x00331cc3 in GMmalloc_zone_malloc ()
#7 0x94f38edb in malloc_set_zone_name ()
#8 0x94f394a8 in _malloc_initialize ()
#9 0x94f3986b in malloc ()
#10 0x00002ef0 in start ()
#11 0x00013f1d in std::_List_const_iterator<Tone> std::max_element<std::_List_const_iterator<Tone>, bool (*)(Tone const&, Tone const&)>(std::_List_const_iterator<Tone>, std::_List_const_iterator<Tone>, bool (*)(Tone const&, Tone const&)) at /Developer/of_007_iphone/apps/cwi007/SingXO/SingXO/Pitch/pitch.hh:25
#12 0x000139b2 in Analyzer::findTone(double, double) const ()
#13 0x00011950 in -[AppDelegate timerCallback:] ()
#14 0x00115308 in -[CCTimer update:] ()
#15 0x0011e124 in -[CCScheduler tick:] ()
#16 0x0014993a in -[CCDirectorIOS drawScene] ()
#17 0x0014bda4 in -[CCDirectorDisplayLink mainLoop:] ()
#18 0x007baa88 in CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long) ()
#19 0x007babcd in CA::Display::EmulatorDisplayLink::callback(__CFRunLoopTimer*, void*) ()
#20 0x019c88c3 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#21 0x019c9e74 in __CFRunLoopDoTimer ()
#22 0x019262c9 in __CFRunLoopRun ()
#23 0x01925840 in CFRunLoopRunSpecific ()
#24 0x01925761 in CFRunLoopRunInMode ()
#25 0x020bb1c4 in GSEventRunModal ()
#26 0x020bb289 in GSEventRun ()
#27 0x00beac93 in UIApplicationMain ()
#28 0x00002fb6 in main ()
我也在控制台中得到了这个:
GuardMalloc[MyApp-723]: *** mmap(size=2097152) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
哦,当然,这就是NOW似乎可能成为罪魁祸首的功能:
- (void)timerCallback:(NSTimer *)timer {
Tone const * tone = audio->analyzer->findTone();
if (tone && tone->db > kToneMinDB) {
self.currentPitch = tone->freq;
self.currentVolume = tone->stabledb;
self.currentNoteName = [NSString stringWithCString:scale->getNoteStr(tone->freq).c_str() encoding:NSUTF8StringEncoding];
// NSLog(@"Current Note Name in timerCallback: %@", currentNoteName);
self.currentNoteFunction = [pitchFilter getPitchFunctionFromPitchName:currentNoteName];
} else {
self.currentNoteName = @"--";
self.currentNoteFunction = -1;
}
}
我不明白程序在没有有效音调的情况下如何进入if (tone)
块,或者反过来说如果音调有效它会如何崩溃。帮助
(这很长。我应该在更集中的问题中删除一些吗?)
我在想的事情: 1.这是一个线程问题:: shudder ::其中一个线程正在改变音频数据而另一个正在读取它。 在timerCallback函数中有些东西正在破坏,我不知道,堆栈是因为它经常分配。这个函数被调用很多,但不是一个极端的数量;每150毫秒安排一次。
不知道为什么其中任何一个都会在模拟器中出现问题,但在设备上不会出现问题。
答案 0 :(得分:1)
C ++参考永远不能是0
/ NULL
。如果是的话,你已经进入了Undefined Territory。如果参数可能是0
,则必须在执行链中移动测试。
也就是说,dbCompare
唯一格式良好的版本如下所示:
struct Tone {
static bool dbCompare(Tone const& l, Tone const& r) {
return l.db < r.db;
}
};
的更新强> 的
如果迭代时调整大小,那么迭代器将无效 - 我不认为在此实现中发生了这种情况。你是从另一个线程调整容器的大小吗?
另外,尝试使用GuardMalloc运行它 - 它旨在让这些问题显而易见。通过更快失败,它将更加本地化(在许多情况下)。
答案 1 :(得分:1)
'best =&amp; * it'行对我来说很奇怪。容器是通过引用还是值存储?看起来你可能正在返回临时存储的地址。这可能会导致问题。