shared_ptr 与 new 运算符:使用哪个
shared_ptr vs. new operator: which one to use
在下面的函数中,当发出特定请求时,我使用了 cpprestsdk (https://github.com/Microsoft/cpprestsdk) to make http requests to a network camera. The function below is probably a callback called by the lcm library (http://lcm-proj.github.io/) 中的 http_client
。
我在第 11 行遇到了问题。我之前使用的是 new 运算符:
auto init_session_response = new init_session_response_t;
创建指针并在退出函数之前手动删除它。
但是在第 49 行的 pplx 任务延续中尝试修改 init_session_response
对象时出现访问冲突异常。
init_session_response->status_code =
ptz_camera::status_codes_t::OK;
当我开始使用 std::shared_ptr 时,这个问题就消失了。有人可以向我解释为什么使用 shared_ptr 可以解决问题吗? http_client* 是否也应该使用 std::shared_ptr 创建?
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}
当您遇到违规访问错误时,您必须删除代码中某些地方的指针(例如,在某些 then
lambda 中),但您没有 post 您的代码使用原始指针所以我不能说是哪一行。
通过使用std::shared_ptr
,当它传递给lambda时,它被值捕获,所以它增加了use_count
并确保init_session_response
有效并且在labmda中没有被破坏,解决了这个问题。
在下面的函数中,当发出特定请求时,我使用了 cpprestsdk (https://github.com/Microsoft/cpprestsdk) to make http requests to a network camera. The function below is probably a callback called by the lcm library (http://lcm-proj.github.io/) 中的 http_client
。
我在第 11 行遇到了问题。我之前使用的是 new 运算符:
auto init_session_response = new init_session_response_t;
创建指针并在退出函数之前手动删除它。
但是在第 49 行的 pplx 任务延续中尝试修改 init_session_response
对象时出现访问冲突异常。
init_session_response->status_code =
ptz_camera::status_codes_t::OK;
当我开始使用 std::shared_ptr 时,这个问题就消失了。有人可以向我解释为什么使用 shared_ptr 可以解决问题吗? http_client* 是否也应该使用 std::shared_ptr 创建?
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}
当您遇到违规访问错误时,您必须删除代码中某些地方的指针(例如,在某些 then
lambda 中),但您没有 post 您的代码使用原始指针所以我不能说是哪一行。
通过使用std::shared_ptr
,当它传递给lambda时,它被值捕获,所以它增加了use_count
并确保init_session_response
有效并且在labmda中没有被破坏,解决了这个问题。