Stackoverflow и функциональные указатели - PullRequest
5 голосов
/ 22 мая 2011

Я совершенно заблудился в этом, и я надеюсь, что кто-то здесь может помочь.

Мое приложение состоит из сотен функций, оценивающих числовой код (источник находится в диапазоне 5 МБ каждая), и я управляю функциями с помощьюstd::map для работы указателей.Очевидно, что я получаю переполнение стека при попытке передать аргумент одной из функций, к которой обращается указатель на нее:

Вывод GDB:

Program received signal SIGSEGV, Segmentation fault.
0x0000000001ec0df7 in xsectiond149 (sme=Cannot access memory at address 0x7fffff34b888
) at xsection149.c:2
2       Poly3 xsectiond149(std::tr1::unordered_map<int, Poly3> & sme, 
                           EvaluationNode::Ptr ti[], ProcessVars & s)

и xsection149.c: 2 имеет только открывающую скобку для определения функции.

/proc/<pid>/map для процесса показывает диапазон адресов, ближайший к адресу, который вызывает ошибку только в этой строке:

7ffffff74000-7ffffffff000 rw-p 7ffffff73000 00:00 0                      [stack]

поэтому адрес в приведенной выше ошибке выходит за пределы.

Теперь мой вопрос: как мне решить эту проблему?Я не могу обернуть голову относительно того, что я мог бы выделить в куче ...

Единственное, что происходит в моей основной программе:

// A map containing O(10^4) Poly3 (struct with 6 doubles)
tr1::unordered_map<int, Poly3> smetemp;
// populates smetemp
computeSMEs(smetemp);
// Map of function pointers of type, O(10^3) elements
tr1::unordered_map<int, xsdptr> diagfunctions = get_diagram_map(); 

Как это могло бы переполнитьстек ??

РЕДАКТИРОВАТЬ: Я пытался запустить его в valgrind, я получаю эту ошибку, и Google не дал никакой значимой информации:

valgrind: m_debuginfo/storage.c:417 (vgModuleLocal_addDiCfSI): 
    Assertion 'cfsi.len < 5000000' failed.
==491==    at 0x38029D5C: ??? (in /usr/lib64/valgrind/memcheck-amd64-linux)

EDIT2: Разборка функции до точки, где она перестала работать (0x0000000001ec0df7), дает мне:

Dump of assembler code for function xsectiond149(std::tr1::unordered_map<int, Poly3,      std::tr1::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, Poly3> >,   false>&, std::vector<boost::shared_ptr<EvaluationNode>,    std::allocator<boost::shared_ptr<EvaluationNode> > >&, ProcessVars&):
<...+0>:      push   %rbp                                                               
<...+1>:      mov    %rsp,%rbp                                                          
<...+4>:      push   %r15                                                               
<...+6>:      push   %r14                                                               
<...+8>:      push   %r13                                                               
<...+10>:     push   %r12                                                               
<...+12>:     push   %rbx                                                               
<...+13>:     sub    $0xc96b58,%rsp                                                     
<...+20>:     mov    %rdi,%rbx                                                          
<...+23>:     mov    %rsi,-0xc8b078(%rbp)      // this instr fails                                         

и первые несколько строк функции читаются:

Poly3 xsectiond149(std::tr1::unordered_map<int, Poly3> & sme,   
                   std::vector<EvaluationNode::Ptr> & ti, 
                   ProcessVars & s)
{
    Poly3 sum(0,0,0,-2);
    Poly3 prefactor, expr;

    // CF*CA^2*NF*NA^(-2)
    double col0 = 0.5625000000000000000000000000;

    prefactor = col0*ti[0]->value()*s.Qtpow2*s.epow2*s.gpow6;
    expr =       (128*(s.p1p2*sme[192]*s.mt - s.p1p2*sme[193]*s.mt +
       1/2.*s.p1p2*sme[195]*s.mt - 1/2.*s.p1p2*sme[196]*s.mt -
       s.p1p2*sme[201]*s.mt + s.p1p2*sme[202]*s.mt +
       1/2.*s.p1p2*sme[210]*s.mt - 1/2.*s.p1p2*sme[211]*s.mt -
       1/4.*s.p1p2*sme[216]*s.mt + 1/4.*s.p1p2*sme[217]*s.mt -
       s.p1p2*sme[219]*s.mt + s.p1p2*sme[220]*s.mt -
       1/8.*s.p1p2*sme[1209]*s.mt + 1/8.*s.p1p2*sme[1210]*s.mt +
       1/2.*s.p1p2*sme[1215]*s.mt - 1/2.*s.p1p2*sme[1216]*s.mt +
   // .....
}

(Примечаниечто я изменил сигнатуру функции во время эксперимента)

Может кто-нибудь свести концы с концами того, что здесь происходит?Какая дополнительная информация вам нужна?Извините, но у меня почти нет опыта работы с asm.

EDIT3 : Увеличение размера стека с помощью ulimit -s <size> добилось цели.Спасибо всем за помощь!

Ответы [ 2 ]

5 голосов
/ 22 мая 2011

Похоже, что функции xsectiond149 требуется кадр стека размером около 13 МБ (обратите внимание на инструкцию sub $0xc96b58,%rsp и сбой, как только она попытается что-то записать, двумя инструкциями позже).Вы должны убедиться, что поток имеет достаточно большой стек (по умолчанию он не будет) перед вызовом функции.

Вы также можете посмотреть, как изменить генератор кода, чтобы распределять больше содержимого в куче вместостек.

2 голосов
/ 22 мая 2011

Получите Valgrind и запустите вашу программу под Valgrind (используя memcheck, инструмент по умолчанию) после сборки.Таким образом, вам будет намного легче найти источник ошибки.

Вы также можете запустить Valgrind в режиме, когда он ломается в отладчик (обычно GDB), и затем вы можете использовать все классные команды GDB.проверять значения в кадрах стека вызывающих абонентов и т. д.

В любом случае, если вы застряли, Valgrind должен помочь вам найти некоторые указатели, где продолжить.

Что касается вашего редактирования, вот мойответ (цитата из исходного кода Valgrind, r11604 из storage.c):

445     /* sanity */
446     vg_assert(cfsi.len > 0);
447     /* If this fails, the implication is you have a single procedure
448     with more than 5 million bytes of code. Which is pretty
449     unlikely. Either that, or the debuginfo reader is somehow
450     broken. 5 million is of course arbitrary; but it's big enough
451     to be bigger than the size of any plausible piece of code that
452     would fall within a single procedure. */
453     vg_assert(cfsi.len < 5000000); 
...