【问题标题】:Is there a way to save a value across multiple executions of a C++ application?有没有办法在 C++ 应用程序的多次执行中保存一个值?
【发布时间】:2017-11-23 05:57:43
【问题描述】:

例如,

int var;
int main() {
    if(var==5) {
        cout<<"Program has been run before"<<endl;
    }
    else {
        var = 5;
        cout<<"First run"<<endl;
    }
}

这将打印 First run the first time,并且 Program has been run before each time after。这可能吗?

编辑:一个文件不起作用,还有其他方法吗?

【问题讨论】:

  • 唯一的标准机制是使用文件。其他解决方案将取决于平台。
  • @FrançoisAndrieux 你碰巧知道任何依赖于平台的解决方案吗?
  • 只有普通文件不能工作(数据库能工作)?你的目标平台是什么? Linux?窗户?
  • @nefas 数据库将是最后的手段。 Linux,RHEL 6。
  • 出于兴趣,为什么文件不起作用?

标签: c++ variables save global-variables


【解决方案1】:

您需要将该计数器保存在应用程序之外的某个位置。变量存储在为进程保留的内存中。因此,当您的进程终止时,内存中的值也会消失。

如果一个平面文件不起作用,其他选项可能是一个数据库,甚至可能是一个单独的守护程序来跟踪某个应用程序的运行时间。但是,如果您想在电源循环期间保持计数器,则需要将该数据值保存在持久内存中的某个位置(例如硬盘驱动器)

【讨论】:

  • 我之前注意到这个答案很早就被否决了,当时它仍然只有 1 或 2 个句子。人们可能对最初的不完整答案投了反对票,并且从未复查过。最初,您的回答只是说“您需要将该计数器保存在应用程序之外的某个位置。”
  • 啊对,他们确实画得很快。这是几秒钟的事情。但是谢谢,我认为反对票是针对第 1 版的。
  • 我听说有些人建议尽快发布答案,作为获得更多代表的“技巧”,然后通过编辑完成答案。也许它与其他社区一起工作,但 c++ 社区在分发反对票时相当无情。
【解决方案2】:

好的,下面是它的要点:

如果您正在运行的内核没有提供文件,您需要提供有关您正在使用的内核和/或设备的具体详细信息,以及是否需要在“重新启动”之间存储它们,因为无法创建文件听起来很具体。

如果您没有任何 flash/hdd/ssd 或其他类型的“硬”来保存数据,则在执行之间保存值是不可能的,由于 RAM 的动态特性,您无法将值保存在 RAM 中。

你可以做的是:

a) 编写你自己的原始 fs 管理工具,如果你的架构只运行你的应用程序,这应该很容易,因为你不需要做很多检查,但你需要有一个静态内存来存储字节到

b) 在执行结束时重新编译初始程序并将您想要替换的值替换为当前程序中存在的值

c) 使用 shell 将值保存在一些外部变量中:

   #include <stdlib.h>

   putenv("EXTERNAL_STATE=" + my_variable);

d) 通过网络将您希望保存的状态发送到具有文件系统的机器并从那里读取/写入。

e) 有一个单独的应用程序在一段时间内运行并监听来自控制台的输入。当它接收到集合输入时,它以所述变量作为参数运行您的程序,当您的程序返回时,它输出变量,“父”应用程序读取它并在内部设置它

【讨论】:

  • 对于导出方案,将变量导出到程序外,只从程序中修改不是更好吗?据我记得,export 将变量导出给孩子。程序停止后,如果程序父级未导出该变量,则该变量将被删除。 (我不确定,如果我错了,请见谅)
  • 可能是这样,添加了一种更明确的方法,但是 env 变量和它们的处理方式无论如何都是系统特定的。我什至不确定它是 posix 的一部分
【解决方案3】:

我想到了使用来自 boost 库的共享内存

这个概念是,程序第一次运行时,它会创建自己的另一个进程,只需使用特定参数调用(是的,它是一种分叉,但这样我们就有了一个可移植的解决方案)。并行进程只是处理共享内存的初始化,并等待终止信号。

以下实现的主要缺点是,理论上,client(不是管理器)的共享内存可以在 server(它处理共享内存)已完成初始化。

哦,我只是打印以0为底的运行索引,只是为了演示。代码在这里。

#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <csignal>

#include <boost/process.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

static constexpr const char* daemonizer_string = "--daemon";
static constexpr const char* shared_memory_name = "shared_memory";

static std::mutex waiter_mutex;
static std::condition_variable waiter_cv;

struct shared_data_type
{
    std::size_t count = 0;
};

extern "C"
void signal_handler(int)
{
    waiter_cv.notify_one();
}

int main(int argc, const char* argv[])
{
    namespace bp = boost::process;
    namespace bi = boost::interprocess;

    if(argc == 2 and std::strcmp(argv[1], daemonizer_string) == 0)
    {
        struct shm_remove
        {
            shm_remove() { bi::shared_memory_object::remove("shared_memory"); }
            ~shm_remove() { bi::shared_memory_object::remove("shared_memory"); }
        } shm_remover;

        bi::shared_memory_object shm(bi::create_only, shared_memory_name, bi::read_write);

        shm.truncate(sizeof(shared_data_type));
        bi::mapped_region region(shm, bi::read_write);
        void* region_address = region.get_address();
        shared_data_type* shared_data = new (region_address) shared_data_type;

        std::signal(SIGTERM, signal_handler);

        {
            std::unique_lock<std::mutex> lock(waiter_mutex);
            waiter_cv.wait(lock);
        }

        shared_data->~shared_data_type();
    }
    else
    {
        bi::shared_memory_object shm;
        try
        {
            shm = bi::shared_memory_object(bi::open_only, shared_memory_name, bi::read_write);
        }
        catch(std::exception&)
        {
            using namespace std::literals::chrono_literals;
            bp::spawn(argv[0], daemonizer_string);
            std::this_thread::sleep_for(100ms);
            shm = bi::shared_memory_object(bi::open_only, shared_memory_name, bi::read_write);
        }

        bi::mapped_region region(shm, bi::read_write);
        shared_data_type& shared_data = *static_cast<shared_data_type*>(region.get_address());
        std::cout << shared_data.count++ << '\n'; 
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2021-06-07
    • 2022-12-13
    • 2021-09-12
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    相关资源
    最近更新 更多