有没有办法在C ++应用程序的多次执行中保存值?

时间:2017-06-20 15:32:02

标签: c++ variables save global-variables

例如,

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

这将打印首次运行首次运行,并且每次运行之前都已运行程序。这有可能吗?

编辑:文件无法正常工作,还有其他方法吗?

3 个答案:

答案 0 :(得分:7)

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

如果平面文件不起作用,其他选项可能是数据库,甚至可能是一个单独的守护程序,它跟踪某个应用程序的运行时间。但是如果你想让计数器超过电源周期,你需要将数据值保存在持久存储器中的某个地方(例如硬盘)

答案 1 :(得分:1)

好的,所以这里有它的主旨:

如果您运行的内核没有提供文件,您需要提供有关您正在使用的内核和/或设备的具体详细信息,以及是否需要将它们存储在&#34; reboots&#34;之间,无法包装文件听起来非常具体。

如果你没有任何flash / hdd / ssd或其他类型的&#34; hard&#34;要保存数据,在执行之间保存值是不可能的,由于其动态特性,您无法在RAM中保存值。

你能做的是:

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

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

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

   #include <stdlib.h>

   putenv("EXTERNAL_STATE=" + my_variable);

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

e)让一个单独的应用程序在一段时间内运行并侦听来自控制台的输入。当它接收到集合输入时,它以所述变量作为参数运行你的程序,当你的程序返回它时输出变量和&#34; parent&#34;应用程序读取它并在内部设置

答案 2 :(得分:1)

我想出了使用boost库中的共享内存的想法。

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

以下实现的主要缺点是,理论上,客户端(而不是管理器)的共享内存可以在服务器之前打开(其处理共享内存)已完成初始化。

哦,我只是打印基数为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'; 
    }
}