2016-07-12 22 views
0

In der Funktion unten habe ich http_client von cpprestsdk (https://github.com/Microsoft/cpprestsdk) verwendet, um HTTP-Anfragen an eine Netzwerkkamera zu machen. Die folgende Funktion ist wahrscheinlich ein Callback, der von der lcm-Bibliothek (http://lcm-proj.github.io/) aufgerufen wird, wenn eine bestimmte Anfrage gestellt wird.shared_ptr vs. neuer Operator: welcher zu verwenden

Ich hatte Probleme mit der Linie 11. Ich zuvor den neuen Operator wurde:

auto init_session_response = new init_session_response_t; 

die Zeiger zu erstellen und manuell einfach gelöscht werden, bevor die Funktion verlassen. Aber ich habe Ausnahme eine Zugriffsverletzung beim Versuch, das init_session_response Objekt in der pplx Aufgabe Fortsetzung 49. in Zeile

init_session_response->status_code = 
       ptz_camera::status_codes_t::OK; 

Dieses Problem ging weg zu ändern, wenn ich mit std :: shared_ptr gestartet. Kann mir jemand erklären, warum die Verwendung von shared_ptr das Problem gelöst hat? Soll der http_client * auch mit std :: shared_ptr erstellt werden?

1 void lcm_handler::on_init_session_req(const lcm::ReceiveBuffer* rbuff, 
2 const std::string& channel, 
3 const ptz_camera::init_session_request_t* req) 
4 { 
5  std::cout << "Received init session req on channel: " << channel << 
6  "; Camera: " << req->ip_address << std::endl; 
7 
8 auto ip_address = req->ip_address; 
9 
10 // Note use of std::shared_ptr 
11 auto init_session_response = make_shared<ptz_camera::init_session_response_t>(); 
12 
13 auto key_position = this->ip_client_map.find(ip_address); 
14 if (key_position == ip_client_map.end()) 
15 { 
16  std::cout << "Creating a new client for the ip: " 
17   << req->ip_address << endl; 
18 
19  wstring username = this->convert_to_wstring(req->username); 
20  wstring password = this->convert_to_wstring(req->password); 
21 
22  wstring main_uri = L"http://" + convert_to_wstring(ip_address); 
23  auto config = http_client_config(); 
24  auto login = credentials(username, password); 
25  config.set_credentials(login); 
26  config.set_timeout(std::chrono::milliseconds(500)); 
27 
28  http_client* client = new http_client(main_uri, config); 
29  std::cout << "Client created...\n"; 
30 
31  uri_builder uri = uri_builder(U("/") + uri_constants::stw_cgi). 
32   append_path(uri_constants::attributes_cgi).append_path(uri_constants::attributes); 
33 
34  auto request = uri.to_string(); 
35 
36  client->request(methods::GET, request) 
37   .then([this, ip_address, client, init_session_response] 
38    (pplx::task<http_response> request_task) -> pplx::task<wstring> 
39  { 
40   try 
41   { 
42    auto response = request_task.get(); 
43    if (response.status_code() == status_codes::OK) 
44    { 
45     std::cout << "Saving client..."; 
46     this->ip_client_map[ip_address] = client; 
47     std::cout << "success.\n"; 
48 
49     init_session_response->status_code = 
50     ptz_camera::status_codes_t::OK; 
51    } 
52 
53    else 
54    { 
55     cout << "GET request to client failed! HTTP Error: " 
56      << response.status_code() << std::endl; 
57 
58     init_session_response->status_code = 
59      ptz_camera::status_codes_t::ERR; 
60    } 
61 
62    return response.extract_string(); 
63   } 
64    
65   catch (const exception& e) 
66   { 
67    cout << "Caught exception: " << e.what() << endl; 
68    return create_task([e, this]() -> wstring 
69    { 
70     return convert_to_wstring(e.what()); 
71    }); 
72   }    
73 
74  }) 
75   .then([init_session_response, this](wstring response) 
76  { 
77   string n = this->convert_to_string(response); 
78   init_session_response->response_message = n; 
79  }); 
80 } 
81 
82 
83 else 
84 { 
85  string message = "Client for ip: " + req->ip_address + " already exists\n"; 
86  cout << message << endl; 
87  init_session_response->response_message = message; 
88  init_session_response->status_code = ptz_camera::status_codes_t::OK; 
89 } 
90 
91 this->lcm->publish(ptz_camera_channels::init_session_res_channel, 
92  init_session_response.get()); 
93} 
+3

'shared_ptr' und' new' schließen sich nicht gegenseitig aus, obwohl es eine gute Vorgehensweise ist, sie im Allgemeinen mit 'make_shared' zu behalten. – chris

+0

bedenken Sie mit "löschen" die Folgen sind sofort (mehr oder weniger) - die Objekte aufhören zu gelten. Dies ist relevant, wenn Sie einen Callback/Task einrichten, der auf den Wert nach "delete" verweisen muss, der außerhalb der Prozedur liegen könnte, die das Objekt zuweist (z. B. ein Lambda, das die Adresse als erfassten Wert verwendet). –

+0

Es ist wahrscheinlich besser, den Code zu posten, der * nicht funktioniert * wenn Sie möchten, dass wir herausfinden, warum es nicht funktioniert. – Galik

Antwort

1

Wenn Sie Zugriffsverletzung Fehlermeldung erhalten, müssen Sie den Zeiger in einem Ort in Ihrem Code (zB in einigen then lambdas) gelöscht haben, aber du hast Post nicht, Ihren Code mit Rohzeiger so kann ich nicht sagen, was Linie.

von std::shared_ptr verwenden, wenn es um das Lambda übergeben wird, wird es durch Wert erfaßt ist, so dass er die use_count erhöht und sorgt dafür, dass init_session_response gültig ist und nicht in der labmda zerstört, die das Problem löst.