My application works just fine when I have defined the CAMERA_NAME environment variable, but as soon as I remove that variable from my docker-compose file, the container will return a very useless error message that doesn't give me information such as what variable/line the error is occurring on:
basler-hd | terminate called after throwing an instance of 'std::logic_error'
basler-hd | what(): basic_string::_M_construct null not valid
Here is the relevant code:
try {
char const* camera_name_ = std::getenv("CAMERA_NAME");
if (!camera_name_)
camera_name_ = generate_uuid_v4().c_str();
init_loggers(camera_name_);
SPDLOG_INFO("Camera name (found in environment or was generated): {}", camera_name_);
SPDLOG_INFO("Starting Application.");
PylonInitialize();
mqtt::async_client client(DEFAULT_SERVER_ADDRESS, CLIENT_ID, PERSIST_DIRECTORY);
auto willMessage = mqtt::message("nssams/camera", "Camera Disconnected", 1, true);
auto connectionOptions = mqtt::connect_options_builder()
.clean_session()
.will(willMessage)
.finalize();
std::string ip_address = std::getenv("IP_ADDRESS") != NULL ? std::string(std::getenv("IP_ADDRESS")) : "192.168.0.1";
if (ip_address.compare("192.168.0.1") == 0)
SPDLOG_WARN("No IP address was found in environment, setting to '192.168.0.1'");
std::string camera_name(camera_name_);
// Instantiate Camera instance and connect.
Camera::MqttBaslerCamera camera( client, camera_name );
try {
camera.discover_and_create_device(ip_address);
} catch (Camera::MqttBaslerCamera::DeviceNotFoundException & ex){
SPDLOG_CRITICAL("No device found matching IP [{}] from environment", ip_address);
PylonTerminate();
return 1;
}
camera.connect();
// Assign the Camera instance as the mqtt callback handler.
client.set_callback(camera);
I am just struggling to see what the issue is. I am checking for NULL after I attempt to get a value from the CAMERA_NAME environment variable. If it's NULL, I am setting it to a value before I move on.
I just can't tell where it's crashing because the error message is so vague, and if I add any log/cout statements, they won't even run due to this error so I can't tell at what point it's crashing
CodePudding user response:
To see where the error is from you could use a debugger to step through the code line by line to find where something unexpected is happening.
If it's NULL, I am setting it to a value before I move on.
camera_name_
is a pointer. It is not a string. It can point to a c-string. Here:
camera_name_ = generate_uuid_v4().c_str();
You make it point to the internal buffer of the string returned by generate_uuid_v4()
. If the function returns the string by value then this string is temporary and ceases to exist at the end of the line. The pointer you stored in camera_name_
is then dangling. If the function would return a reference to a string that is stored elsewhere, keeping a pointer to it would be fine.
Don't use a pointer to a string when you actually want to store a string:
#include <string>
#include <iostream>
const char* getenv() {
return nullptr;
}
std::string generate_uid() {
return "asd";
}
int main() {
std::string name;
if (auto env = getenv(); env == nullptr){
name = generate_uid();
} else {
name = std::string(env);
}
std::cout << name;
}
CodePudding user response:
Without more context, one can only guess:
I think this is a logical_error
std::string camera_name(camera_name_);
if camera_name_
is a nullptr
.
Which might be what std::getenv
returns if the system variable is not found.
If this is the problem, the fix depends on what you really want to do with that variable if the environment variable doesn't exists?
std::string camera_name(camera_name_?camera_name_:"defaultName");
Or if you are too cool for C (non-standard)
std::string camera_name(camera_name_?:"defaultName");
In fact you are already doing that for std::string ip_address
.