g ++ неправильно понимает семантику c ++ - PullRequest
1 голос
/ 21 июня 2011

Есть два возможных решения проблемы: я не понимаю семантику c ++ или g ++.

Я сейчас программирую простую сетевую игру. Я строил библиотеку, которую игра использует для общения по сети. Существует класс, предназначенный для обработки соединения между приложениями. Другой класс реализует функциональность сервера, поэтому он обладает методом accept(). Метод должен вернуть класс Connection.

Есть несколько способов вернуть класс. Я пробовал эти три:

Connection accept() {
...
return Connection(...);
}

Connection* accept() {
...
return new Connection(...);
}

Connection& accept() {
...
Connection *temp = new Connection(...);
return *temp;
}

Все три были приняты g ++. Проблема в том, что третья неисправна. Когда вы используете внутреннюю информацию об объекте типа Connection, у вас не получится. Я не знаю, что не так, потому что все поля внутри объекта выглядят как инициализированные. Моя проблема в том, что когда я использую какую-либо функцию из библиотеки буферов протокола, моя программа завершается из-за ошибки сегментации. Приведенная ниже функция дает сбой при каждом вызове библиотеки protobuf. * ​​1009 *

 Annoucement Connection::receive() throw(EmptySocket) {
    if(raw_input->GetErrno() != 0) throw EmptySocket();
    CodedInputStream coded_input(raw_input);
    google::protobuf::uint32 n;
    coded_input.ReadVarint32(&n);
    char *b;
    int m;
    coded_input.GetDirectBufferPointer((const void**)&b, &m);
    Annoucement ann;
    ann.ParseFromArray(b, n);
    coded_input.Skip(n);
    return ann;
  }

Я получаю это каждый раз:

Программа получения сигнала SIGSEGV, Ошибка сегментации. 0x08062106 в Google :: Protobuf :: IO :: FileInputStream :: CopyingFileInputStream :: GetErrno (это = 0x20) в /usr/include/google/protobuf/io/zero_copy_stream_impl.h:104

Когда я сменил accept() на вторую версию, она, наконец, сработала (первая тоже хорошая, но я тем временем изменил концепцию).

Сталкивались ли вы с какой-либо проблемой, подобной этой? Почему третья версия accept() не так? Как мне отладить программу, чтобы найти такую ​​ужасную ошибку (я думал, что protobuf нужно исправить, а проблемы там не было)?

Ответы [ 3 ]

3 голосов
/ 21 июня 2011

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

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

Что касается того, почему он не работает, он, вероятно, связан с семантикой владения, а не с тем, что вы возвращаетесь по ссылке, но я могу 'Не вижу проблемы в размещенном коде.

1 голос
/ 21 июня 2011

"Как мне отладить программу, чтобы найти такую ​​ужасную ошибку?"Если вы работаете в Linux, попробуйте запустить под Valgrind - это должно подхватить любую происходящую строчку памяти.

0 голосов
/ 21 июня 2011

Вы пропустили raw_input = 0x20, который, очевидно, является недействительным указателем.Это в полезном сообщении, которое вы получили в отладчике после segfault.

Для общих проблем такого типа научитесь использовать memcheck от Valgrind, который дает вам сообщения о том, где ваша программа использовала память.

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

...