我为在ARM CortexA9处理器上运行的Linux交叉编译了一个C++应用程序,该处理器因SIGFPE/Arithmetic异常而崩溃.最初我认为这是因为gcc 的-O3标志引入了一些优化,但后来我在调试模式下构建它仍然崩溃.
我使用gdb调试了应用程序,它捕获了异常,但不幸的是,触发异常的操作似乎也使堆栈无效,因此我无法获得有关该代码中导致这种情况发生的位置的任何详细信息.我最终得到的唯一细节是触发异常的操作(来自下面的堆栈跟踪):
3 raise() 0x402720ac
2 __aeabi_uldivmod() 0x400bb0b8
1 __divsi3() 0x400b9880
Run Code Online (Sandbox Code Playgroud)
该__aeabi_uldivmod() ,所以我尝试蛮力方法,并搜查了我的代码,因为它被证明是一项艰巨的任务,可能会使用操作,但没有取得多大成功的地方正在执行一个unsigned long长除法和提醒.此外,我试图通过零来检查潜在的划分,但再次检查代码库是否非常大并且检查每个除法操作这是一个麻烦且有些愚蠢的方法.所以必须有一个更聪明的方法来弄清楚发生了什么.
当调试器无法帮助时,是否有任何技术可以追踪此类异常的原因?
更新:在对十六进制数字进行处理,转储内存和进行堆栈取证之后(感谢Crashworks)我在ARM编译器文档中遇到了这个gem(即使我没有使用ARM Ltd.编译器):
通过重新实现适当的C库辅助函数,可以捕获并识别整数除零错误.除以零时的默认行为是,当使用信号函数或重新实现__rt_raise()或__aeabi_idiv0()时,调用__aeabi_idiv0().否则,除法函数返回零.__aeabi_idiv0()使用附加参数DIVBYZERO引发SIGFPE.
所以我在__aeabi_idiv0(_aeabi_ldiv0)et Voila上放了一个断点!在完全删除之前我有完整的堆栈跟踪.感谢大家提供的非常丰富的答案!
免责声明:"获胜"答案是单独和主观地选择考虑到其建议对我的调试工作的重量,因为不止一个是提供信息,真的很有帮助.
我有一个为多个操作系统(现在是Linux和Windows,可能是OS X)和处理器而构建的项目.对于这个项目,我有一些库依赖项,它们是男性外部的,但我有几个内部的,以源代码形式,我为我的上下文中可能的每个OS处理器组合编译(交叉编译).
大多数外部库不会经常更改,只是在本地错误修复或某个功能\ bugfix在较新版本中实现的情况下,我认为它可能会对项目有所帮助.内部库经常更改(1个月周期)并由我公司的另一个团队以二进制形式提供,虽然我也可以访问源代码,如果我需要修复错误,我可以这样做并生成新的二进制文件我的使用直到下一个发布周期.我现在的设置如下(仅限文件系统):
-- dependencies
|
-- library_A_v1.0
|
--include
|
--lib
|
-- library_A_v1.2
|
--include
|
--lib
|
-- library_B
|
--include
|
--lib
| ...
Run Code Online (Sandbox Code Playgroud)
这些库保存在服务器上,每次进行更新时,我都必须在服务器上复制任何新的二进制文件和头文件.客户端上的同步使用文件同步实用程序完成.当然,对库的任何更新都需要向其他开发人员公布,每个人都必须记住同步他们的"依赖"文件夹.
不用说,我不太喜欢这个计划.所以我想把我的库放在版本控制(GIT)下.构建它们,将它们打包成tgz\zip并将它们推送到repo上.每个库都有自己的git存储库,这样我就可以轻松地标记\ branch已经使用过的版本和测试驱动器的新版本.每个库的"数据流",我可以轻松获取,组合,更新.我想要以下内容:
摆脱这种保存库的正常文件系统方式; 现在,为每个操作系统和每个版本保存和管理完整的单独文件夹,有时它们不同步导致混乱
更多地控制它,能够清楚地了解我们用于哪个版本的项目的库的版本; 很像我们可以从git(VCS)获得的源代码
能够标记\分支我正在使用的依赖项的版本(对于它们中的每一个); 我有我的v2.0.0标签/分支用于library_A我通常把它用于我的项目,但我想测试驱动2.1.0版本,所以我只是构建它,在不同分支上的服务器上推送它并调用我的构建脚本,这个特定的依赖项指向新的分支
有更简单的构建脚本 - 只需从服务器中提取源,拉动依赖项并构建; 这也允许对不同的处理器-OSO组合使用相同库的不同版本(通常我们需要)
我试图找到基于git的直接解决方案的一些替代方案,但没有太大成功 - 比如git-annex,这对于我正在尝试做的事情似乎过于复杂.
我现在面临的事实是,似乎非常强烈反对将二进制文件放在git或任何VCS下(尽管技术上我也会有头文件;我也可以将我直接描述的文件夹结构推送到git没有tgz\zip,但我仍然会有图书馆二进制文件)而且我的一些同事,在这个共同的强烈意见的推动下,反对这种方案.我完全理解git跟踪内容而不是文件,但在某种程度上我会跟踪内容,我相信它肯定会比我们现在的方案有所改进.
对于这种情况,什么是更好的解决方案?你知道基于git(VCS)的方案的任何替代品吗?将我的计划置于git :)下会是一件多么可怕的事吗?请分享您的意见,特别是您在处理这些类型情况时的经验.
谢谢
有谁知道Observer aka Listener模式的替代方案?我对在异步环境中运行良好的东西很感兴趣.
我面临的问题是我有一个使用这种模式的应用程序,这本身并不是一件坏事,但随着监听器数量的增加,它成为一个瓶颈.结合线程原语(互斥体,关键部分 - 当然在我的特定环境中),对性能的打击非常糟糕.
oop performance multithreading design-patterns observer-pattern
我有以下代码:
typedef int AliasB;
typedef unsigned short AliasA;
class Alias
{
public:
explicit Alias(int someInt) { }
};
// (*) !! below breaks the conversion path via AliasA !!
//typedef Alias AliasA;
class C
{
public:
C() { }
};
class B
{
public:
B() { }
B(const AliasB& value) { }
operator AliasB() const
{
return -1000;
}
C combine(const B& someB)
{
return C();
}
};
class A
{
public:
A() { }
operator B() const
{
return …Run Code Online (Sandbox Code Playgroud) 为了使程序具有高效缓存,所使用的数据应该线性存储吗?
因此,我使用线性分配器将数据放入blob中,而不是动态分配.这是否应该提高性能?我该怎么做才能进一步提高缓存效率?
我知道这些问题不具体,但我不知道如何解释......
哪些程序可以帮助我分析缓存命中/未命中?
我有一个广泛使用模板的源文件。在该文件中,我还具有不同模板的显式实例化…很多。该文件被编译为静态库的一部分。我在多个平台上为多个体系结构编译了该库:Win x86,Linux x86和Linux ARM。对于Linux版本,我使用不同的编译器,因此生成的文件(在ELF文件本身的上下文中讨论)是不同的:对于GCC,生成的目标文件大小为8.4MB,并具有超过40000个ELF节;对于ARM编译器(armcc),结果文件的大小为12.7MB,并具有超过90000个ELF节(!);在两种情况下,我都有调试信息。
发生的情况是,在链接时,ARM链接器试图将静态库中的巨大目标文件链接起来而死掉了。经过一番调查,看来它无法处理其中包含超过65536个ELF部分的目标文件(尽管我仍然必须从编译器供应商处获得确认,否则我将完全或完全错误地做某件事)。我发现的解决方案是将文件拆分为多个较小的文件(它的结构以及允许的内容)。
问题:还有其他替代解决方案吗?在链接阶段之前,编译器是否有可能在目标文件中(在模板的上下文中)生成额外的代码?
请考虑以下代码:
#include <iostream>
#include <tuple>
#include <utility>
// A.
template <typename... Args>
void f (const char* msg, Args&&... args)
{
std::cout << "A. " << msg << "\n";
}
// B.
template <typename... Args>
void f (const char* msg, std::tuple<Args...>&& t)
{
std::cout << "B. " << msg << "\n";
}
struct boo
{
const std::tuple<int, int, long> g () const
{
return std::make_tuple(2, 4, 12345);
}
};
int main ()
{
f("First", 2, 5, 12345);
f("Second", std::make_tuple(2, 5, 12345)); …Run Code Online (Sandbox Code Playgroud) 给出以下代码(取自此处):
#include <cstddef>
#include <type_traits>
#include <tuple>
#include <iostream>
#include <utility>
#include <functional>
template<typename ... Fs>
struct compose_impl
{
compose_impl(Fs&& ... fs) : functionTuple(std::forward_as_tuple(fs ...)) {}
template<size_t N, typename ... Ts>
auto apply(std::integral_constant<size_t, N>, Ts&& ... ts) const
{
return apply(std::integral_constant<size_t, N - 1>(), std::get<N> (functionTuple)(std::forward<Ts>(ts)...));
}
template<typename ... Ts>
auto apply(std::integral_constant<size_t, 0>, Ts&& ... ts) const
{
return std::get<0>(functionTuple)(std::forward<Ts>(ts)...);
}
template<typename ... Ts>
auto operator()(Ts&& ... ts) const
{
return apply(std::integral_constant<size_t, sizeof ... (Fs) - 1>(), std::forward<Ts>(ts)...); …Run Code Online (Sandbox Code Playgroud) 我想知道 pthread_join 中的“status”参数到底是用来做什么的
int pthread_join(pthread_t thread, void **status);
Run Code Online (Sandbox Code Playgroud)
我正在尝试利用它,但我无法理解它到底代表什么。根据文档
地位
Run Code Online (Sandbox Code Playgroud)Is the location where the exit status of the joined thread is stored.如果不需要退出状态,可以将其设置为 NULL。
好的。听起来不错。我该如何使用它?我看过一些例子,但我无法掌握它的窍门(有些例子在使用它时是完全错误的)。所以我确实去了源头。在 glibc 实现中,我发现了以下 pthread_join 测试:
...
pthread_t mh = (pthread_t) arg;
void *result;
...
if (pthread_join (mh, &result) != 0)
{
puts ("join failed");
exit (1);
}
here follows the WTF moment ...
if (result != (void *) 42l)
{
printf ("result wrong: expected %p, got %p\n", (void *) 42, result);
exit (1);
}
Run Code Online (Sandbox Code Playgroud)
所以结果(这是一个地址)的值应该是42? …
我在使用GCC for ARM时出现了一个非常奇怪的问题,并且启用了优化.在没有优化的情况下编译我的C++应用程序会生成一个可执行文件,在运行时输出预期的结果.一旦我打开优化 - 即-O1 - 我的应用程序就无法产生预期的结果.我试了几天才发现问题,但我很无能为力.我从我的代码中删除了任何未初始化的变量,我纠正了严格混叠可能导致问题但仍然没有正确结果的位置.
我正在使用GCC 4.2.0 for ARM(处理器是ARM926ej-s)并在Montavista Linux发行版上运行该应用程序.
以下是我正在使用的标志:
-O1 -fno-unroll-loops fno-merge-constants -fno-omit-frame-pointer -fno-toplevel-reorder \
-fno-defer-pop -fno-function-cse -Wuninitialized -Wstrict-aliasing=3 -Wstrict-overflow=3 \
-fsigned-char -march=armv5te -mtune=arm926ej-s -ffast-math
Run Code Online (Sandbox Code Playgroud)
一旦我剥离-O1标志并重新编译/重新链接应用程序,我就会得到正确的输出结果.正如你从旗帜中看到我试图禁用任何优化我认为它可能会导致问题,但仍然没有运气.
有没有人对如何进一步解决这个问题有任何指示?
谢谢
我正在学习 Golang,作为使用接口的练习,我正在构建一个玩具程序。我在尝试使用“应该实现”两个接口的类型时遇到了一些问题 - 在 C++ 和 Java 中解决这个问题的一种方法是使用继承(还有其他技术,但我认为这是最常见的)。由于我在 Golang 中缺乏这种机制,我不确定如何进行。下面是代码:
var (
faces = []string{"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"}
suits = []string{"Hearts", "Diamonds", "Spades", "Clubs"}
)
type Card interface {
GetFace() string
GetSuit() string
}
type card struct {
cardNum int
face string
suit string
}
func NewCard(num int) Card {
newCard := card{
cardNum: num,
face: faces[num%len(faces)],
suit: suits[num/len(faces)],
}
return &newCard
}
func (c *card) GetFace() string {
return c.face …Run Code Online (Sandbox Code Playgroud) 为什么我们需要delete语句?
const MyString& operator=(const MyString& rhs)
{
if (this != &rhs) {
delete[] this->str; // Why is this required?
this->str = new char[strlen(rhs.str) + 1]; // allocate new memory
strcpy(this->str, rhs.str); // copy characters
this->length = rhs.length; // copy length
}
return *this; // return self-reference so cascaded assignment works
}
Run Code Online (Sandbox Code Playgroud)