LINUX.ORG.RU

[C++]Причины SIGSEGV

 


0

3

Такое себе продолжение предыдущего треда. Есть в проекте класс

class Client: public QObject
{
public:
  Client(QObject* parent) : QObject(parent) {}
  ~Client() {}
...
private:
  class ClientPrivate;
  ClientPrivate *d;
};

Из конструктора и деструктора был выкинут весь код.

Наблюдается сегфолт при выполнении данного кода:

delete new Client(NULL);

Падает в деструкторе, непонятно с какого залезая в libfam.so. valgrind способен лишь констатировать смерть (т.е. находить проблемы уже в libfam, который никаким краем вызываться не должен).

Если рядом с Client определить точно такой же Client1, то, в зависимости от взаимного положения классов в коде, сегфолта может и не быть.

Подозревается повреждение памяти, но вопрос скорее теоретического плана: что нужно повредить, чтобы в однопоточном приложении в delete new Client(); фейлился деструктор? Причем фейлился еще до вызова operator delete(void*).

★★★★★

вопрос скорее практического плана: что нужно курить, чтобы делать «delete new Client()»?

yoghurt ★★★★★
()

habr с его статьей о pImpl перечитал?

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

вопрос скорее практического плана: что нужно курить, чтобы делать «delete new Client()»?

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

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

P.S. И да - проект не мой, это kopete.

Pavval ★★★★★
() автор топика

вопрос скорее теоретического плана: что нужно повредить, чтобы в однопоточном приложении в delete new Client(); фейлился деструктор? Причем фейлился еще до вызова operator delete(void*).

Heap нужно повредить.

mv ★★★★★
()
#include <QtCore/QCoreApplication>
#include <iostream>

namespace test {

class ClientPrivate {
};

class Client: public QObject{
public:
  Client(QObject* parent = 0) : QObject(parent) {}
  ~Client() {}

  void check() {
      std::cout << "Client method 'check' is surely callable." << std::endl;
  }

private:
  class ClientPrivate;
  ClientPrivate *d;
};

}

int main(int argc, char *argv[]) {

    QCoreApplication a(argc, argv);

    test::Client* client;
    client = new test::Client();

    client->check();

    delete client;

    return 0;
}

УМВР, что надо сделать чтобы оно сломалось?

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

Heap нужно повредить.

А подробнее? Можешь привести пример повреждения, которое вызовет эту проблему?

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

УМВР, что надо сделать чтобы оно сломалось?

Ты не понял - проблема возникает в конкретном проекте в конкретном классе из-за неясного бага, который я и пытаюсь отловить. В других условиях сегфолта не будет.

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

Ты не понял - проблема возникает в конкретном проекте в конкретном классе из-за неясного бага, который я и пытаюсь отловить. В других условиях сегфолта не будет.

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

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

Есть проект, в котором этот код фейлится. Как фейлится, я рассказал. Меня интересуют теоретические выкладки на тему возможных причин этого фейла.

Проект не мой, но я очень хочу найти причину и починить.

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

Думаешь я не знаю, что такое ошибки при работе с памятью? Я не вчера программировать начал.

Какая именно ошибка приведет к такому поведению? Память чего должна быть испорчена?

Pavval ★★★★★
() автор топика

> Наблюдается сегфолт при выполнении данного кода:

Падает в деструкторе,


а где именно? в деструкторе QObject?

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

Есть проект, в котором этот код фейлится. Как фейлится, я рассказал. Меня интересуют теоретические выкладки на тему возможных причин этого фейла.

1. без конкретики, Вы участников форума пытаетесь мотивировать на стрельбу по дерьму (хуже чем вентилятор)
2. неужели так сложно посмотреть в google почему sisegv может вылетать?
3. хотите найти причину - ищите, возьмите strace посмотрите на каком шаге конкретно отваливается

и, если уж говорить про причину:

For a seg-fault
- you didn't initialise it
- you didn't allocate it
- you messed around with the pointer (like walked it off the end of an array)
- you freed it, then tried to access it
- you messed up the malloc size calculation to begin with
- you didn't prototype malloc to begin with
- you returned a pointer to a local variable
All these, and many more, are ways you could have screwed up.
shty ★★★★★
()
Ответ на: комментарий от aho

а где именно? в деструкторе QObject?

Нет, в ~Client

Судя про прогулке по ассемблерному коду в ~QObject оно даже не заходит. Но и до delete не доберается. Я вообще откровенно не понял, что там творится - ничего понятного в асме деструктора нету. Вместо очевидного вызова ~QObject там какой-то call или jmp по захардкодженому в команде (т.е. не вычисляемому при выполнении) адресу, где творится вообще хз что.

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

Думаешь я не знаю, что такое ошибки при работе с памятью? Я не вчера программировать начал.

не знаю насчёт Вашего общего стажа, но, судя по вопросам, именно с С++ Вы мало дел имели

Какая именно ошибка приведет к такому поведению? Память чего должна быть испорчена?

я вот никак не пойму, у меня ник babawanga что-ли?

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

Чувак, ты меня явно вчитаешь дебилом, который не знает, от чего происходит sigsegv. Я ясно спрашиваю: «память чего должна быть повреждена, чтобы delete new A() вызывал сегфлот». Если для тебя этот вопрос не является конкретным, то ты просто его не понимаешь. В таком случае я бы порекоммендовал просто пройти мимо этого треда, а не засорять его рекоммендациями для школьников.

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

Я ясно спрашиваю: «память чего должна быть повреждена, чтобы delete new A() вызывал сегфлот».

ну, отвечая точно на Ваш вопрос: память копьютера, ёп

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

Если это всё, на что ты способен, то просто проходи мимо. Капитанов Очевидность в этот тред не звали.

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

А подробнее? Можешь привести пример повреждения, которое вызовет эту проблему?

Покорёжил чужой пойнтер. Код, котому этот пойнтер принадлежит (libfam у тебя, вроде), сунулся по пойнтеру, а там дырка от бублика, а не память.

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

Покорёжил чужой пойнтер. Код, котому этот пойнтер принадлежит (libfam у тебя, вроде), сунулся по пойнтеру, а там дырка от бублика, а не память.

Не совсем понял.

Код, в котором падает - это или деструктор Client, который ничего не содержит, или (что не подтверждается backtrace) деструктор QObject. Client не имеет childов, потому деструктор QObject тоже не должен ничего полезного делать. Вокруг кода libfam'ом вообще не пахнет. Вызов libfam - скорее всего ошибка. Само падение происходит после вызова libfam. (и если внезапно была вызвана левая функция, то я не удивлюсь результирующему падению).

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

Память испортилась задолго до того, как программа упала. Вероятно, испорчена служебная структура аллокатора, если сегфолт получается от delete new пустого класса.

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

Память испортилась задолго до того, как программа упала. Вероятно, испорчена служебная структура аллокатора, если сегфолт получается от delete new пустого класса.

Звучит правдоподобно.

Но есть проблема: я только что попробовал рядом с Client определить другой класс (такой же функциональности) и создавая его методом delete new Client1() перед delete new Client() получаю проблемы в разных классах в зависимости (пока точно не определил) от имен и относительного расположения определений классов. Сейчас попробую точнее найти зависимость.

Pavval ★★★★★
() автор топика

> вопрос скорее теоретического плана: что нужно повредить, чтобы в однопоточном приложении в delete new Client(); фейлился деструктор? Причем фейлился еще до вызова operator delete(void*).

Чисто теоретический ответ: VPTR или VTBL.

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

Итак:

Тестим класс «Client» перед «Clien» при том, что Client определен в коде (и h и cpp) после Clien - нет креша.

Тестим класс «Clie» перед «Clien» при том, что Clie определен в коде (и h и cpp) после Clien - нет креша.

Тестим класс «Clie» перед «Clien» при том, что Clie определен в коде (и h и cpp) до Clien - нет креша.

Тестим класс «Client» перед «Clien» при том, что Client определен в коде (и h и cpp) до Clien - креш.

Жесть.

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

> А VTBL доступна для записи?

Вот честно скажу: ХЗ. Теоретически, не должна, но кто знает все детали реализации...

tailgunner ★★★★★
()

ты можешь продолжать и найти 500 тысяч мест, в которых оно будет работать, и столько же мест, в которых будет падать. Тебе нужно искать где ты порешь heap.

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

в mac os есть удобная библиотека - libgmalloc, возможно что-то похожее есть и для линукса, но мне попадались только такие, что отлавливают только утечки

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

Итак: > Жесть.

Типичные стуки в погребе при запортаченной памяти.

Я в одном случае ошибся, итого: файл зависит от ИМЕНИ КЛАССА, и не зависит от положения в коде.

test Client before Clien    Client is after Clien   - crash
test Clie before Clien    Clie is after Clien   - nothing
test Clie before Clien    Clie is before Clien   - nothing
test Client before Clien    Client is before Clien   - crash

Думаю что буду отлаживать и сравнивать асм в обеих случаях.

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

ТС отлдачик не уважаете ? учите ассемблер поставьте точек прерывания в подозрительных местах проверок понапихайте везде вокруг гиблого места примените всю артиллерию и может быть вам повезет если баг не совсем злой на си не знать ассемблер гиблое дело если за тобой попу не подтирают другие

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

наверное я, но не уверен

Откуда ты знаешь такие интимные подробности, что там на неправославном маке есть?

mv ★★★★★
()

Госпади... да дайте ему уже помереть спокойно(((( Я туда заглядывал пару раз и местами ужасался. Код с многолетним наслоением от совершенно разных людей, разных поколений, кое как портированный на Qt4.

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

> Откуда ты знаешь такие интимные подробности, что там на неправославном маке есть?

ну так вестимо - от работы «на неправославном маке», не часто, но бывает

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

Пока telepathy-kde не дописан — помирать не дадим :)

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

как думаете это говно имеет право на жизнь ? цепепе сука заставляет по всему коду делать говнокастинг потому что alloca возвращает oid * соорудил эту какашку

struct sja_alloca
{
	size_t size;
	
	sja_alloca(size_t size)
		: size(size) {}
	
	template <class T>
	operator T *()
	{
		return (T *)alloca(size);
	}
};
...
sometype * ptr = sja_alloca(size);

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

цепепе сука заставляет по всему коду делать говнокастинг потому что alloca возвращает void *

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

вообще как программировать на цепепе 90% функций отдают void * везде гребаный говнокастинг из за этого в си таких трабл нет я про системный программинг

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

Кхм... я не понял, причем это к поиску гипотеттически кривого VPTR, но мне не нравится возврат за пределы функции указателя на память, выделенную alloca.

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

вот эта пистец вот это я лоханулся тото я вчера похееоил код и переписал по другому как же это я додумался память от alloca из функции возвращать вчера я столько проибался с мичтическими глюками из за этого пока все не переписал по другому (без sja_alloca) кстати трындец как я мог так накосячить

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

я же главное знаю что память освобождается при выходе от alloca автоматически и такое написал а вчера ибался с мистическими глюками списал все на кривизну стыдно сказать системного апи ))))))) пиздец пора в больничку

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

как программировать на цепепе 90% функций отдают void * везде гребаный говнокастинг из за этого

Не пишите функций, которые возврящают void*, и все будет хорошо. Про русский язык я вообще молчу.

Идиотский вопрос - если Client1 не фейлится (тоже потомок QObject?), что будет, если во всем kopete переименовать? Это пляски с бубном, конечно, но учитывая, что падает в какой-то левой либе - может что-то с линковкой? Правда, не представляю, как такой может быть?

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

Не пишите функций, которые возврящают void*, и все будет хорошо.

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

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