Google Protobuf: "mutable_foo ()" или "set_allocated_foo ()"? - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь использовать протобуф Google.Я использую subMessage, я устанавливаю его со случайными значениями и сохраняю subMessage в mainMessage.Вот примеры сообщений, которые соответствуют моему случаю:

message subMessage{
    required int32 val1= 1;
    required int32 val2= 2;
    required int32 val3= 3;
    required int32 val4= 4;
}

message mainMessage{
    required subMessage sub = 1;
}

Мой основной:

int main (int argc,char** argv){
    subMessage sM;
    mainMessage mM;
    sM.set_val1(10);
    sM.set_val2(9);
    sM.set_val3(8);
    sM.set_val4(7);

Затем я попытался:

mM.set_allocated_submessage(&sM);

, но это привело к ошибке сегментациив конце программы (Уничтожение объекта?).Единственный способ решить эту проблему - это вручную вызвать mM.release_submessage();.

Я также попытался:

*mM.mutable_submessage()=subMessage;

Я не понимаю, почему у меня возникает ошибка сегментации, так как моя программа останавливается сразу после(Нет доступа / записи к моему subMessage или моему mainMessage).
Согласно документации Google :

void set_allocated_foo (Bar * bar) :Устанавливает объект Bar в поле и освобождает предыдущее значение поля, если оно существует.Если указатель Bar не равен NULL, сообщение становится владельцем выделенного объекта Bar и has_foo () вернет true.В противном случае, если Bar равен NULL, поведение аналогично вызову clear_foo ()

. Кажется, что mainMessage имеет владельца после set_allocated_foo(), но это приводит к ошибке сегментации.С другой стороны, mutable_foo(), кажется, дублирует данные.Я хотел бы избежать дублирования данных, так как я собираюсь работать на Raspberry с низким объемом оперативной памяти, но set_allocated_foo() слишком загадочно для меня на данный момент.Я не понимаю разницы между этими двумя ...

Как вы думаете, я должен использовать .set_allocated_foo() и вручную отпустить или использовать .mutable_foo()?

Спасибо.

PS: мне известна эта тема о set_allocated_foo () , но моя проблема не в удалении или нет, а скорее в правах на указатели / данные и не помогла мне решить мою проблему

1 Ответ

0 голосов
/ 06 декабря 2018

Ваш код удаляет ЛОКАЛЬНУЮ переменную оператором delete.Это неопределенное поведение.Ваша проблема в том, что вы передаете указатель на переменную LOCAL, вы должны выделить subMessage на new, затем вы можете передать его в mainMessage.

int main()
{
    subMessage sM;  // [1]
    mainMessage mM; 
    sM.set_val1(10);
    sM.set_val2(9);
    sM.set_val3(8);
    sM.set_val4(7);
    mM.set_allocated_submessage(&sM); // [2]

    // calls dtors in reverse order of definitions of instances
    dtor on mM is called // [3]
    dtor on sM is called // [4]
}

Короче:

[1] sM создается как локальная переменная

[2] вы передаете указатель на локальную переменную sM, в этот момент mM становится владельцем sM

[3] и поскольку mM вступил во владение sM, он пытается удалить sM в dtor, вызвав delete ptrToSm

[4], вероятно, эта точка никогда не достигается, приложение упало

Решение:

 subMessage* sM = new ...;
 mM.set_allocated_submessage(sM);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...