В C ++ передача указателя все еще копирует объект? - PullRequest
2 голосов
/ 22 сентября 2009

Я читаю уже час и до сих пор не понимаю, что происходит с моим приложением. Поскольку я использую экземпляры объекта с new и delete, мне нужно управлять памятью самостоятельно. Мое приложение должно иметь длительное время безотказной работы, и поэтому правильное управление потреблением памяти очень важно для меня.

Вот статическая функция, которую я использую для выгрузки пакета данных, который передается между ПК и платой ввода-вывода в обоих направлениях. Пакет данных представляет собой массив BYTE с и инкапсулируется в объект, либо DCCmd, либо DCReply (оба являются реализацией абстрактного DCMessage класса).

void DebugTools::dumpBytes(BYTE* bytes, short length)
{
    printf("       |---DUMPING DATAPACKET refId: %d ....\n", &bytes);
    for(short i=0; i<length; i++){
        printf("       | B%d | %.2X\n", i, bytes[i]);
    }
    printf("       |---END DUMP           refId: %d ....\n", &bytes);
}

Тогда есть такой вариант использования: я создаю объект DCCmd и добавляю его в очередь исходящих сообщений для отправки. «Насос» (бесконечный цикл) проверяет исходящие сообщения и передает любые кандидаты в одноэлементный объект IOConnector.

DCCmd* cmd = new DCCmd(DIG_CMD_SELFTEST_RES);
cmd->add(param);
printf("cmdSelfTest()\n"); //HACK
BYTE* cmda = cmd->getBytes(); //HACK
DebugTools::dumpBytes(cmda, cmd->getLength()); //HACK
sendMsg(cmd);

... и добавление в очередь:

bool DC::sendMsg(DCMessage* msg)
{
    if(isOnline()){
        outbox->add(msg);
        return true;
    } else {
        return false;
    }
}

Добавление в очередь производится с помощью void add(DCMessage* msg);

(В классе соединителей есть еще один из этих dumpBytes(), чтобы увидеть, что действительно будет отправлено)

Но вот вывод:

TESTING MESSAGE QUEUES ....
cmdSelfTest()
       |---DUMPING DATAPACKET refId: 2489136 ....
       | B0 | C6
       | B1 | A1
       | B2 | 00
       | B3 | 01
       | B4 | 10
       | B5 | 00
       | B6 | 01
       | B7 | 78
       |---END DUMP           refId: 2489136 ....
    adding to queue: 2488884
   queues: inbox (0), outbox (1)
send: sending candidates....
  sending 2489164 ....
    >->-> ...
       |---DUMPING DATAPACKET refId: 2488704 ....
       | B0 | C6
       | B1 | A1
       | B2 | 00
       | B3 | 01
       | B4 | 10
       | B5 | 00
       | B6 | 01
       | B7 | 78
       |---END DUMP           refId: 2488704 ....
Packet sent!
. ((second iteration of the pump))
   queues: inbox (0), outbox (1)
send: sending candidates....
  sending 2489164 ....
    >->-> ...
       |---DUMPING DATAPACKET refId: 2488704 ....
       | B0 | C6
       | B1 | A1
       | B2 | 00
       | B3 | 01
       | B4 | 10
       | B5 | 00
       | B6 | 01
       | B7 | 78
       |---END DUMP           refId: 2488704 ....
Packet sent!

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

Ответы [ 3 ]

5 голосов
/ 22 сентября 2009

Переменная байты - это указатель на данные, то есть место в памяти данных. Но это не то, что вы печатаете, вы распечатываете адрес, где находится этот указатель, то есть адрес в стеке, куда передается указатель. Так

printf("       |---DUMPING DATAPACKET refId: %d ....\n", &bytes);

должно быть просто

printf("       |---DUMPING DATAPACKET refId: %d ....\n", bytes);
1 голос
/ 22 сентября 2009

В своих вызовах к dumpBytes вы передавали байты, используя передачу по копии вместо передачи по ссылке.

В результате создается новый указатель на байты для времени жизни dumpBytes. В зависимости от вашей системы это будет 8,16,32,64 байта и т. Д. Другими словами, если у вас действительно очень жесткие ограничения памяти, это не проблема.

1 голос
/ 22 сентября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...