LINUX.ORG.RU

Пара вопросов о стеке (+)


0

0

Вопрос номер 1.
В ходе дебага одной софтины
столкнулся с такой ситуацией:
выполняю программу пошагово
и вижу такое
if(SomeFunc()){
printf("mega error");
}
else{
printf("all OK");
}
трейсинг SomeFunc
показывает что она возвращает -1
то бишь по коду мы должны попадать
на printf("mega error"); однако,
попадаем на printf("all OK");

баг проявляеться после пары недель работы
проги, я предпологаю что баг вызван какимто
хитрым повреждением стека, возможно просто
не достали со стека переменную какую-то,
(в проге широко используються функции с переменным
количеством операндов) или еще что
однако прога продолжает работать, неверно работать
а мне как-то нужно найти баг.
Хотелось бы услышать советы людей которые
сталкивались с подобными ситуациями,
а также советы на тему, как мне этот баг выловить.

Вопрос номер 2.
Есть код типа
Func1(){
...
Func2(){
pid = fork();
if(pid == 0){
long_time_func();
}
}

}
в общем куча функций вложеных одна в другую
в каждой создаеться на стеке куча автоматических переменных
что естественно занимает определенную память
софтина критична к объему потребляемой памяти
поэтому чтобы в форке освободить эту память на стеке
я делаю такой код
if(PROC_TYPE == LONG_PROC) return;
и так до самого майна
в котором уже делаю непосредственный вызов
нужной функции
main{
....
if(PROC_TYPE == LONG_PROC) some_func();
}
Вопрос состоит в том есть ли какой-то другой
более элегантный способ освобождения стека ?

anonymous

Попробуй поискать в коде #define true = и #define false = .Если такое найдется можешь смело выкладывать код в жж code_wtf :)

signal
()

по второму вопросу: почему ты хочешь освободить стэк? Если ты его не освободишь то ты боишься что превысишь лимит стека? Если не боишься, то я не вижу никакой нужды его "освобождать", потому что реально ты ничего не выигрываешь

По поводу более элегантного освобождения: setjmp/longjmp не поможет?

dilmah ★★★★★
()
Ответ на: комментарий от signal

krum@krum:~/test$ cat test.c #include <stdio.h> #include <stdlib.h> int main(int argc,char** argv){ if(-1) printf("-1==true\n"); else printf("-1==false\n"); return 0; } krum@krum:~/test$ gcc test.c -o test krum@krum:~/test$ ./test -1==true

krum
()
Ответ на: комментарий от signal

krum@krum:~/test$ cat test.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char** argv){
        if(-1)
                printf("-1==true\n");
        else
                printf("-1==false\n");
        return 0;
}
krum@krum:~/test$ gcc test.c -o test
krum@krum:~/test$ ./test
-1==true


krum
()

по первому вопросу -- как то не верится что дело в порче стэка, потому что если функция возвращает один int, то большинство компиляторов возвращают его в регистре

dilmah ★★★★★
()

> возможно просто не достали со стека переменную какую-то, (в проге широко используються функции с переменным количеством операндов)

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

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

Я ведь уже привёл причину "бага" - незнание языка С. Марш читать K&R "Язык С"! И хватит бредит о том, о чём понятия не имеешь. Или иди учить Java, так такого "бага" не может быть.

krum
()
Ответ на: комментарий от krum

по моему ты плохо прочел то что он написал:

f(SomeFunc()){
printf("mega error");
}
else{
printf("all OK");
}
трейсинг SomeFunc
показывает что она возвращает -1
то бишь по коду мы должны попадать
на printf("mega error"); однако,
попадаем на printf("all OK");

я не вижу здесь незнания Си++

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

2 dilmah
за setjmp/longjmp
спасибо, возможно
это действительно то что мне нужно
как-то никогда не использовал, читаю уже маны в общем :)

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

и вот в один прекрасный момент
все замолкает, захожу на машину
смотрю пид нужного процеса
атачу к нему GDB и вижу описаную ситуацию

функция возвращает только инт
если ответ в регистре то реально такого быть не может
поэтому всеже думаю что на стеке,
чесно говоря сам удивлен увиденным, сейчас
сижу вкуриваю доки по GDB на тему того чтобы
глянуть что где как конкретно передаеться

однако всеже интуитивно похоже на какие-то непонятки
со стеком, ибо были похожие ситуацие в других кусках кода

еще попутный вопрос
а можно ли как-то сделать
что-то типа дампа процеса для дальнейшего изучения ?
а то баги проявляються через недели, а серваки рабочие,
ковыряться часами нету возможности, приходить глянуть по
быстрому и ребутать демона да и все
а в тестовых условиях чет как-то воспроизвести не удаеться



anonymous
()
Ответ на: комментарий от anonymous

> еще попутный вопрос а можно ли как-то сделать что-то типа дампа процеса для дальнейшего изучения ? а то баги проявляються через недели, а серваки рабочие, ковыряться часами нету возможности, приходить глянуть по быстрому и ребутать демона да и все а в тестовых условиях чет как-то воспроизвести не удаеться

gcore

dilmah ★★★★★
()

> Вопрос состоит в том есть ли какой-то другой
более элегантный способ освобождения стека ? 

есть, даже два :)
во первых не порождать 'кучу вложенных функций' на С,
и второй - забить на эту проблему, ибо она проблемой не является :)
поверьте на слово - порождение процесса весьма экономно по памяти 

можно проверить (псевдокод), вместо breakpoint`ов - коментарии
int main() {
  char xlargearray[XLARGE_SIZE];
  // тут смотрим сколько реально отожрано памяти
  memset(xlargearray,0,XLARGE_SIZE];
  // тут снова смотрим - должно отожраться
  if (fork()==0) {
     // потомок - должно не сильно увеличться
     memset(xlargearray,1,XLARGE_SIZE);
     // а вот теперь - да, отъето
    
  } else {

  }
}

MKuznetsov ★★★★★
()
Ответ на: комментарий от anonymous

А как ты ловишь что функция тебе -1 вернула? результат ведь у тебя не сохраняется в переменную ? ;-)

Имхо если и есть ошибка то не в этом if'е )

libc
()

По первому вопросу - фигня какая то. Либо какая то глючная оптимизация (невероятно), либо отладочная информация глючная (теоретически возможно), либо ты путаешь что то (скорее всего).

Искать ошибку - очевидно нужно вести лог, в который записывать каждый чих вокруг того места, где по-твоему прячется баг. И конечно не if (SomeFunc()) а int err = SomeFunc(); log(err); if (err) { log("if successed"); ... и т. д.

И, обязательно, прогу тестить под valgrind-ом, он иногда помогает. Если позволяет производительность, можно даже в боевом режиме запустить под ним.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.