سؤال

في C++, وأنا أعلم أن المترجم أن يختار تهيئة الأجسام الساكنة في أي أمر أنه يختار (تخضع لبعض القيود) ، وذلك في العام لا يمكنك اختيار أو تحديد ثابت تهيئة النظام.

ومع ذلك, مرة واحدة في البرنامج وقد تم تجميع المحول البرمجي لا بد أن يكون قرارا حول ما أجل تهيئة هذه الكائنات. هل هناك أي طريقة لتحديد من ترجمة البرنامج مع رموز تصحيح الأخطاء في ما أمر ثابت المنشئات سوف يكون اسمه ؟

السياق هو هذا:لدي كبير برنامج فجأة segfaulting قبل main() عندما يتم بناؤه تحت toolchain.إما هذا هو ثابت التهيئة مشكلة في الطلب ، أو هو شيء خاطئ مع إحدى المكتبات أن يتم تحميل.ومع ذلك ، عندما كنت التصحيح مع gdb الحادث الموقع هو ببساطة كما ذكرت الخام العنوان دون أي معلومات رمزي أو تعقب.أود أن تقرر أي من هاتين المشكلتين هو عن طريق وضع نقطة توقف في منشئ أول ثابت-تهيئة كائن, ولكن أنا لا أعرف كيف أن أقول أي كائن.

هل كانت مفيدة؟

المحلول

ماثيو ويلسون يوفر طريقة للإجابة على هذا السؤال في هذا القسم (سفاري الكتب على الانترنت الاشتراك المطلوبة) من الكمال C++.(كتاب جيد بالمناسبة) لتلخيص, انه يخلق CUTrace.h رأس أن يخلق ثابت سبيل المثال من الفئة التي يطبع اسم الملف بما في ذلك الملف المصدر (باستخدام غير قياسي المعالج الماكرو __BASE_FILE__) عندما خلق ، ثم انه يشمل CUTrace.h في كل ملف المصدر.

وهذا يتطلب إعادة تجميع ، ولكن #include "CUTrace.ح" يمكن بسهولة إضافة وإزالة طريق سكربت, لذلك لا ينبغي أن يكون من الصعب جدا لاقامة.

نصائح أخرى

في G++ على لينكس, منشئ ثابت والمدمر يأمر يتحدد من خلال وظيفة المؤشرات في .ctors و .dtors أقسام.مع ملاحظة أن يكفي التصحيح المتاحة, يمكنك فعلا الحصول على تعقب:

(gdb) bt
#0  0xb7fe3402 in __kernel_vsyscall ()
#1  0xb7d59680 in *__GI_raise (sig=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0xb7d5cd68 in *__GI_abort () at abort.c:88
#3  0x08048477 in foo::foo() ()
#4  0x0804844e in __static_initialization_and_destruction_0(int, int) ()
#5  0x0804846a in global constructors keyed to foo_inst ()
#6  0x0804850d in __do_global_ctors_aux ()
#7  0x08048318 in _init ()
#8  0x080484a9 in __libc_csu_init ()
#9  0xb7d4470c in __libc_start_main (main=0x8048414 <main>, argc=1,
    ubp_av=0xbfffcbc4, init=0x8048490 <__libc_csu_init>,
    fini=0x8048480 <__libc_csu_fini>, rtld_fini=0xb7ff2820 <_dl_fini>,
    stack_end=0xbfffcbbc) at libc-start.c:181
#10 0x08048381 in _start () at ../sysdeps/i386/elf/start.S:119

هذا مع التصحيح رموز libc و libstdc++ تثبيت.كما يمكنك أن ترى, تحطم هنا حدث في فو::فو() منشئ ثابت كائن foo_inst.

إذا كنت ترغب في كسر في عملية التهيئة ، ثم هل يمكن تعيين نقطة توقف على __لا_العالمية_ctors_aux الخطوة من خلال التفكيك, أعتقد.أو مجرد الانتظار من أجل أن تحطم للحصول على تعقب مثل المذكورة أعلاه.

يمكنك تهيئة المتغيرات الوهمية في ثابت الفضاء ، ووضع نقاط لكسر الارسال على تلك وظيفة المكالمات ؟

extern "C" int breakOnMe () { return 0 };

int break1 = breakOnMe ();
float pi = 3.1415;
int break2 = breakOnMe ();
myClass x = myClass (1, 2, 3);

ثم في gdb تشغيل break breakOnMe قبل تنفيذ البرنامج.التي ينبغي أن تجعل gdb وقفة قبل كل ثابت التهيئة.

أعتقد أنه يجب أن تعمل ..أنا قليلا صدئ على gdbbing.

يمكنك العثور على النظام " تاس " يجري تهيئة باستخدام قوالب كما أبرز هذا السؤال.أنه يتطلب القليل من رمز التغيير إلى كل من " تاس " أن كنت ترغب في:

// order.h
//

#ifndef INCLUDED_ORDER
#define INCLUDED_ORDER

#include <iostream>

inline int showCountAndFile (const char * file)
{
  static int cnt = 0;
  std::cout << file << ": " << cnt << std::endl;
  ++cnt;
  return cnt;
}

template <int & i>
class A {
  static int j;
};

template <int & i>
int A<i>::j = showCountAndFile (SRC_FILE);

namespace
{
  int dummyGlobal;
}
template class A<dummyGlobal>;

#endif

والفكرة الأساسية هي أن كل تو المختلفة فريدة من نوعها عنوان dummyGlobal و لذلك القالب المختلفة مثيل في كل تو.التهيئة من عضو ثابت النتائج في الدعوة إلى "showCountAndFile" ثم يطبع SRC_FILE (في تو) و القيمة الحالية cnt والتي بالتالي سوف تظهر النظام.

كنت استخدامه على النحو التالي:

static const char * SRC_FILE=__FILE__;
#include "order.h"

int main ()
{
}

g++ يقدم بعض المساعدة في هذا.
ليس المحمولة ولكن أنا متأكد من أن في هذه المرحلة ليس هذا هو المشكلة الرئيسية الخاصة بك.

http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#C_002b_002b-Attributes

في الواقع ، من خلال استخدام ووحدانية يمكنك التحكم في ترتيب initialisation العالمية/الأجسام الساكنة فعال جدا في C++.

على سبيل المثال،:

class Abc
{
public:
    void foo();
};

و المقابلة وجوه محددة على النطاق العالمي:

Abc abc;

ثم لديك الدرجة:

class Def
{
public:
    Def()
    {
        abc.foo();
    }
};

التي لديها أيضا كائن محدد في النطاق العالمي:

Def def;

في هذه الحالة, لم يكن لديك السيطرة على initialisation النظام إذا مواطنه تهيئة أولا ثم فمن المرجح أن البرنامج سوف تحطم لأنه يدعو فو() الأسلوب على Abc الذي لم تم تفعيلها

الحل هو أن تعمل على نطاق عالمي تفعل شيئا مثل هذا:

Abc& abc()
{
    static Abc a;
    return a;
}

ثم مواطنه أن ننظر بشيء من مثل:

class Def
{
public:
    Def()
    {
        abc().foo();
    }
};

هذه الطريقة ، abc هو دائما ضمان أن تكون initialised قبل استخدامها لأن هذا سوف يحدث خلال المكالمة الأولى من حروف() وظيفة.وبالمثل ، يجب أن تفعل الشيء نفسه مع مواطنه كائن العالمية لجعل أنه لن يكون أي غير متوقعة initialisation تبعيات سواء.

Def& def()
{
    static Def d;
    return d;
}

إذا كنت بحاجة إلى رقابة صارمة على النظام من initialisation بالإضافة إلى مجرد التأكد من أن كل شيء هو initialised قبل استخدامها ، وضعت جميع الكائنات العالمية في المفرد كما يلي.

struct Global
{
    Abc abc;
    Def def;
};

Global& global()
{
    static Global g;
    return g;
}

وجعل الإشارات إلى هذه العناصر على النحو التالي:

//..some code
global().abc.foo();
//..more code here
global().def.bar();

بغض النظر عن أي واحد يحصل على مكالمات الأولى, C++ الأعضاء initialisation القواعد سوف تضمن أن حروف و مواطنه الكائنات initialised في الترتيب الذي يتم تعريف في الدرجة العالمية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top